ucl_util.c revision 279549
178344Sobrien/* Copyright (c) 2013, Vsevolod Stakhov
278344Sobrien * All rights reserved.
398184Sgordon *
478344Sobrien * Redistribution and use in source and binary forms, with or without
578344Sobrien * modification, are permitted provided that the following conditions are met:
678344Sobrien *       * Redistributions of source code must retain the above copyright
7140339Sobrien *         notice, this list of conditions and the following disclaimer.
898184Sgordon *       * Redistributions in binary form must reproduce the above copyright
9174461Sdougb *         notice, this list of conditions and the following disclaimer in the
1078344Sobrien *         documentation and/or other materials provided with the distribution.
1178344Sobrien *
1278344Sobrien * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
1378344Sobrien * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1498184Sgordon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1598184Sgordon * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
1678344Sobrien * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1778344Sobrien * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1878344Sobrien * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1978344Sobrien * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2078344Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2198184Sgordon * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2298184Sgordon */
2378344Sobrien
2478344Sobrien#include "ucl.h"
2578344Sobrien#include "ucl_internal.h"
2678344Sobrien#include "ucl_chartable.h"
27#include "kvec.h"
28
29#ifndef _WIN32
30#include <glob.h>
31#endif
32
33#ifdef HAVE_LIBGEN_H
34#include <libgen.h> /* For dirname */
35#endif
36
37typedef kvec_t(ucl_object_t *) ucl_array_t;
38
39#define UCL_ARRAY_GET(ar, obj) ucl_array_t *ar = \
40	(ucl_array_t *)((obj) != NULL ? (obj)->value.av : NULL)
41
42#ifdef HAVE_OPENSSL
43#include <openssl/err.h>
44#include <openssl/sha.h>
45#include <openssl/rsa.h>
46#include <openssl/ssl.h>
47#include <openssl/evp.h>
48#endif
49
50#ifdef CURL_FOUND
51#include <curl/curl.h>
52#endif
53#ifdef HAVE_FETCH_H
54#include <fetch.h>
55#endif
56
57#ifdef _WIN32
58#include <windows.h>
59
60#ifndef PROT_READ
61#define PROT_READ       1
62#endif
63#ifndef PROT_WRITE
64#define PROT_WRITE      2
65#endif
66#ifndef PROT_READWRITE
67#define PROT_READWRITE  3
68#endif
69#ifndef MAP_SHARED
70#define MAP_SHARED      1
71#endif
72#ifndef MAP_PRIVATE
73#define MAP_PRIVATE     2
74#endif
75#ifndef MAP_FAILED
76#define MAP_FAILED      ((void *) -1)
77#endif
78
79#ifdef _WIN32
80#include <limits.h>
81#define NBBY CHAR_BIT
82#endif
83
84static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
85{
86	void *map = NULL;
87	HANDLE handle = INVALID_HANDLE_VALUE;
88
89	switch (prot) {
90	default:
91	case PROT_READ:
92		{
93			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READONLY, 0, length, 0);
94			if (!handle) break;
95			map = (void *) MapViewOfFile(handle, FILE_MAP_READ, 0, 0, length);
96			CloseHandle(handle);
97			break;
98		}
99	case PROT_WRITE:
100		{
101			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
102			if (!handle) break;
103			map = (void *) MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, length);
104			CloseHandle(handle);
105			break;
106		}
107	case PROT_READWRITE:
108		{
109			handle = CreateFileMapping((HANDLE) _get_osfhandle(fd), 0, PAGE_READWRITE, 0, length, 0);
110			if (!handle) break;
111			map = (void *) MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, length);
112			CloseHandle(handle);
113			break;
114		}
115	}
116	if (map == (void *) NULL) {
117		return (void *) MAP_FAILED;
118	}
119	return (void *) ((char *) map + offset);
120}
121
122static int ucl_munmap(void *map,size_t length)
123{
124	if (!UnmapViewOfFile(map)) {
125		return(-1);
126	}
127	return(0);
128}
129
130static char* ucl_realpath(const char *path, char *resolved_path) {
131    char *p;
132    char tmp[MAX_PATH + 1];
133    strncpy(tmp, path, sizeof(tmp)-1);
134    p = tmp;
135    while(*p) {
136        if (*p == '/') *p = '\\';
137        p++;
138    }
139    return _fullpath(resolved_path, tmp, MAX_PATH);
140}
141#else
142#define ucl_mmap mmap
143#define ucl_munmap munmap
144#define ucl_realpath realpath
145#endif
146
147typedef void (*ucl_object_dtor) (ucl_object_t *obj);
148static void ucl_object_free_internal (ucl_object_t *obj, bool allow_rec,
149		ucl_object_dtor dtor);
150static void ucl_object_dtor_unref (ucl_object_t *obj);
151
152static void
153ucl_object_dtor_free (ucl_object_t *obj)
154{
155	if (obj->trash_stack[UCL_TRASH_KEY] != NULL) {
156		UCL_FREE (obj->hh.keylen, obj->trash_stack[UCL_TRASH_KEY]);
157	}
158	if (obj->trash_stack[UCL_TRASH_VALUE] != NULL) {
159		UCL_FREE (obj->len, obj->trash_stack[UCL_TRASH_VALUE]);
160	}
161	/* Do not free ephemeral objects */
162	if ((obj->flags & UCL_OBJECT_EPHEMERAL) == 0) {
163		if (obj->type != UCL_USERDATA) {
164			UCL_FREE (sizeof (ucl_object_t), obj);
165		}
166		else {
167			struct ucl_object_userdata *ud = (struct ucl_object_userdata *)obj;
168			if (ud->dtor) {
169				ud->dtor (obj->value.ud);
170			}
171			UCL_FREE (sizeof (*ud), obj);
172		}
173	}
174}
175
176/*
177 * This is a helper function that performs exactly the same as
178 * `ucl_object_unref` but it doesn't iterate over elements allowing
179 * to use it for individual elements of arrays and multiple values
180 */
181static void
182ucl_object_dtor_unref_single (ucl_object_t *obj)
183{
184	if (obj != NULL) {
185#ifdef HAVE_ATOMIC_BUILTINS
186		unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
187		if (rc == 0) {
188#else
189		if (--obj->ref == 0) {
190#endif
191			ucl_object_free_internal (obj, false, ucl_object_dtor_unref);
192		}
193	}
194}
195
196static void
197ucl_object_dtor_unref (ucl_object_t *obj)
198{
199	if (obj->ref == 0) {
200		ucl_object_dtor_free (obj);
201	}
202	else {
203		/* This may cause dtor unref being called one more time */
204		ucl_object_dtor_unref_single (obj);
205	}
206}
207
208static void
209ucl_object_free_internal (ucl_object_t *obj, bool allow_rec, ucl_object_dtor dtor)
210{
211	ucl_object_t *tmp, *sub;
212
213	while (obj != NULL) {
214		if (obj->type == UCL_ARRAY) {
215			UCL_ARRAY_GET (vec, obj);
216			unsigned int i;
217
218			if (vec != NULL) {
219				for (i = 0; i < vec->n; i ++) {
220					sub = kv_A (*vec, i);
221					if (sub != NULL) {
222						tmp = sub;
223						while (sub) {
224							tmp = sub->next;
225							dtor (sub);
226							sub = tmp;
227						}
228					}
229				}
230				kv_destroy (*vec);
231				UCL_FREE (sizeof (*vec), vec);
232			}
233		}
234		else if (obj->type == UCL_OBJECT) {
235			if (obj->value.ov != NULL) {
236				ucl_hash_destroy (obj->value.ov, (ucl_hash_free_func *)dtor);
237			}
238		}
239		tmp = obj->next;
240		dtor (obj);
241		obj = tmp;
242
243		if (!allow_rec) {
244			break;
245		}
246	}
247}
248
249void
250ucl_object_free (ucl_object_t *obj)
251{
252	ucl_object_free_internal (obj, true, ucl_object_dtor_free);
253}
254
255size_t
256ucl_unescape_json_string (char *str, size_t len)
257{
258	char *t = str, *h = str;
259	int i, uval;
260
261	if (len <= 1) {
262		return len;
263	}
264	/* t is target (tortoise), h is source (hare) */
265
266	while (len) {
267		if (*h == '\\') {
268			h ++;
269			switch (*h) {
270			case 'n':
271				*t++ = '\n';
272				break;
273			case 'r':
274				*t++ = '\r';
275				break;
276			case 'b':
277				*t++ = '\b';
278				break;
279			case 't':
280				*t++ = '\t';
281				break;
282			case 'f':
283				*t++ = '\f';
284				break;
285			case '\\':
286				*t++ = '\\';
287				break;
288			case '"':
289				*t++ = '"';
290				break;
291			case 'u':
292				/* Unicode escape */
293				uval = 0;
294				if (len > 3) {
295					for (i = 0; i < 4; i++) {
296						uval <<= 4;
297						if (isdigit (h[i])) {
298							uval += h[i] - '0';
299						}
300						else if (h[i] >= 'a' && h[i] <= 'f') {
301							uval += h[i] - 'a' + 10;
302						}
303						else if (h[i] >= 'A' && h[i] <= 'F') {
304							uval += h[i] - 'A' + 10;
305						}
306						else {
307							break;
308						}
309					}
310					h += 3;
311					len -= 3;
312					/* Encode */
313					if(uval < 0x80) {
314						t[0] = (char)uval;
315						t ++;
316					}
317					else if(uval < 0x800) {
318						t[0] = 0xC0 + ((uval & 0x7C0) >> 6);
319						t[1] = 0x80 + ((uval & 0x03F));
320						t += 2;
321					}
322					else if(uval < 0x10000) {
323						t[0] = 0xE0 + ((uval & 0xF000) >> 12);
324						t[1] = 0x80 + ((uval & 0x0FC0) >> 6);
325						t[2] = 0x80 + ((uval & 0x003F));
326						t += 3;
327					}
328					else if(uval <= 0x10FFFF) {
329						t[0] = 0xF0 + ((uval & 0x1C0000) >> 18);
330						t[1] = 0x80 + ((uval & 0x03F000) >> 12);
331						t[2] = 0x80 + ((uval & 0x000FC0) >> 6);
332						t[3] = 0x80 + ((uval & 0x00003F));
333						t += 4;
334					}
335					else {
336						*t++ = '?';
337					}
338				}
339				else {
340					*t++ = 'u';
341				}
342				break;
343			default:
344				*t++ = *h;
345				break;
346			}
347			h ++;
348			len --;
349		}
350		else {
351			*t++ = *h++;
352		}
353		len --;
354	}
355	*t = '\0';
356
357	return (t - str);
358}
359
360char *
361ucl_copy_key_trash (const ucl_object_t *obj)
362{
363	ucl_object_t *deconst;
364
365	if (obj == NULL) {
366		return NULL;
367	}
368	if (obj->trash_stack[UCL_TRASH_KEY] == NULL && obj->key != NULL) {
369		deconst = __DECONST (ucl_object_t *, obj);
370		deconst->trash_stack[UCL_TRASH_KEY] = malloc (obj->keylen + 1);
371		if (deconst->trash_stack[UCL_TRASH_KEY] != NULL) {
372			memcpy (deconst->trash_stack[UCL_TRASH_KEY], obj->key, obj->keylen);
373			deconst->trash_stack[UCL_TRASH_KEY][obj->keylen] = '\0';
374		}
375		deconst->key = obj->trash_stack[UCL_TRASH_KEY];
376		deconst->flags |= UCL_OBJECT_ALLOCATED_KEY;
377	}
378
379	return obj->trash_stack[UCL_TRASH_KEY];
380}
381
382char *
383ucl_copy_value_trash (const ucl_object_t *obj)
384{
385	ucl_object_t *deconst;
386
387	if (obj == NULL) {
388		return NULL;
389	}
390	if (obj->trash_stack[UCL_TRASH_VALUE] == NULL) {
391		deconst = __DECONST (ucl_object_t *, obj);
392		if (obj->type == UCL_STRING) {
393
394			/* Special case for strings */
395			deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
396			if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
397				memcpy (deconst->trash_stack[UCL_TRASH_VALUE], obj->value.sv, obj->len);
398				deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
399				deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
400			}
401		}
402		else {
403			/* Just emit value in json notation */
404			deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
405			deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
406		}
407		deconst->flags |= UCL_OBJECT_ALLOCATED_VALUE;
408	}
409	return obj->trash_stack[UCL_TRASH_VALUE];
410}
411
412UCL_EXTERN ucl_object_t*
413ucl_parser_get_object (struct ucl_parser *parser)
414{
415	if (parser->state != UCL_STATE_ERROR && parser->top_obj != NULL) {
416		return ucl_object_ref (parser->top_obj);
417	}
418
419	return NULL;
420}
421
422UCL_EXTERN void
423ucl_parser_free (struct ucl_parser *parser)
424{
425	struct ucl_stack *stack, *stmp;
426	struct ucl_macro *macro, *mtmp;
427	struct ucl_chunk *chunk, *ctmp;
428	struct ucl_pubkey *key, *ktmp;
429	struct ucl_variable *var, *vtmp;
430
431	if (parser == NULL) {
432		return;
433	}
434
435	if (parser->top_obj != NULL) {
436		ucl_object_unref (parser->top_obj);
437	}
438
439	LL_FOREACH_SAFE (parser->stack, stack, stmp) {
440		free (stack);
441	}
442	HASH_ITER (hh, parser->macroes, macro, mtmp) {
443		free (macro->name);
444		HASH_DEL (parser->macroes, macro);
445		UCL_FREE (sizeof (struct ucl_macro), macro);
446	}
447	LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) {
448		UCL_FREE (sizeof (struct ucl_chunk), chunk);
449	}
450	LL_FOREACH_SAFE (parser->keys, key, ktmp) {
451		UCL_FREE (sizeof (struct ucl_pubkey), key);
452	}
453	LL_FOREACH_SAFE (parser->variables, var, vtmp) {
454		free (var->value);
455		free (var->var);
456		UCL_FREE (sizeof (struct ucl_variable), var);
457	}
458
459	if (parser->err != NULL) {
460		utstring_free (parser->err);
461	}
462
463	if (parser->cur_file) {
464		free (parser->cur_file);
465	}
466
467	UCL_FREE (sizeof (struct ucl_parser), parser);
468}
469
470UCL_EXTERN const char *
471ucl_parser_get_error(struct ucl_parser *parser)
472{
473	if (parser == NULL) {
474		return NULL;
475	}
476
477	if (parser->err == NULL)
478		return NULL;
479
480	return utstring_body(parser->err);
481}
482
483UCL_EXTERN void
484ucl_parser_clear_error(struct ucl_parser *parser)
485{
486	if (parser != NULL && parser->err != NULL) {
487		utstring_free(parser->err);
488		parser->err = NULL;
489	}
490}
491
492UCL_EXTERN bool
493ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
494{
495#ifndef HAVE_OPENSSL
496	ucl_create_err (&parser->err, "cannot check signatures without openssl");
497	return false;
498#else
499# if (OPENSSL_VERSION_NUMBER < 0x10000000L)
500	ucl_create_err (&parser->err, "cannot check signatures, openssl version is unsupported");
501	return EXIT_FAILURE;
502# else
503	struct ucl_pubkey *nkey;
504	BIO *mem;
505
506	mem = BIO_new_mem_buf ((void *)key, len);
507	nkey = UCL_ALLOC (sizeof (struct ucl_pubkey));
508	if (nkey == NULL) {
509		ucl_create_err (&parser->err, "cannot allocate memory for key");
510		return false;
511	}
512	nkey->key = PEM_read_bio_PUBKEY (mem, &nkey->key, NULL, NULL);
513	BIO_free (mem);
514	if (nkey->key == NULL) {
515		UCL_FREE (sizeof (struct ucl_pubkey), nkey);
516		ucl_create_err (&parser->err, "%s",
517				ERR_error_string (ERR_get_error (), NULL));
518		return false;
519	}
520	LL_PREPEND (parser->keys, nkey);
521# endif
522#endif
523	return true;
524}
525
526#ifdef CURL_FOUND
527struct ucl_curl_cbdata {
528	unsigned char *buf;
529	size_t buflen;
530};
531
532static size_t
533ucl_curl_write_callback (void* contents, size_t size, size_t nmemb, void* ud)
534{
535	struct ucl_curl_cbdata *cbdata = ud;
536	size_t realsize = size * nmemb;
537
538	cbdata->buf = realloc (cbdata->buf, cbdata->buflen + realsize + 1);
539	if (cbdata->buf == NULL) {
540		return 0;
541	}
542
543	memcpy (&(cbdata->buf[cbdata->buflen]), contents, realsize);
544	cbdata->buflen += realsize;
545	cbdata->buf[cbdata->buflen] = 0;
546
547	return realsize;
548}
549#endif
550
551/**
552 * Fetch a url and save results to the memory buffer
553 * @param url url to fetch
554 * @param len length of url
555 * @param buf target buffer
556 * @param buflen target length
557 * @return
558 */
559static bool
560ucl_fetch_url (const unsigned char *url, unsigned char **buf, size_t *buflen,
561		UT_string **err, bool must_exist)
562{
563
564#ifdef HAVE_FETCH_H
565	struct url *fetch_url;
566	struct url_stat us;
567	FILE *in;
568
569	fetch_url = fetchParseURL (url);
570	if (fetch_url == NULL) {
571		ucl_create_err (err, "invalid URL %s: %s",
572				url, strerror (errno));
573		return false;
574	}
575	if ((in = fetchXGet (fetch_url, &us, "")) == NULL) {
576		if (!must_exist) {
577			ucl_create_err (err, "cannot fetch URL %s: %s",
578				url, strerror (errno));
579		}
580		fetchFreeURL (fetch_url);
581		return false;
582	}
583
584	*buflen = us.size;
585	*buf = malloc (*buflen);
586	if (*buf == NULL) {
587		ucl_create_err (err, "cannot allocate buffer for URL %s: %s",
588				url, strerror (errno));
589		fclose (in);
590		fetchFreeURL (fetch_url);
591		return false;
592	}
593
594	if (fread (*buf, *buflen, 1, in) != 1) {
595		ucl_create_err (err, "cannot read URL %s: %s",
596				url, strerror (errno));
597		fclose (in);
598		fetchFreeURL (fetch_url);
599		return false;
600	}
601
602	fetchFreeURL (fetch_url);
603	return true;
604#elif defined(CURL_FOUND)
605	CURL *curl;
606	int r;
607	struct ucl_curl_cbdata cbdata;
608
609	curl = curl_easy_init ();
610	if (curl == NULL) {
611		ucl_create_err (err, "CURL interface is broken");
612		return false;
613	}
614	if ((r = curl_easy_setopt (curl, CURLOPT_URL, url)) != CURLE_OK) {
615		ucl_create_err (err, "invalid URL %s: %s",
616				url, curl_easy_strerror (r));
617		curl_easy_cleanup (curl);
618		return false;
619	}
620	curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ucl_curl_write_callback);
621	cbdata.buf = *buf;
622	cbdata.buflen = *buflen;
623	curl_easy_setopt (curl, CURLOPT_WRITEDATA, &cbdata);
624
625	if ((r = curl_easy_perform (curl)) != CURLE_OK) {
626		if (!must_exist) {
627			ucl_create_err (err, "error fetching URL %s: %s",
628				url, curl_easy_strerror (r));
629		}
630		curl_easy_cleanup (curl);
631		if (cbdata.buf) {
632			free (cbdata.buf);
633		}
634		return false;
635	}
636	*buf = cbdata.buf;
637	*buflen = cbdata.buflen;
638
639	return true;
640#else
641	ucl_create_err (err, "URL support is disabled");
642	return false;
643#endif
644}
645
646/**
647 * Fetch a file and save results to the memory buffer
648 * @param filename filename to fetch
649 * @param len length of filename
650 * @param buf target buffer
651 * @param buflen target length
652 * @return
653 */
654static bool
655ucl_fetch_file (const unsigned char *filename, unsigned char **buf, size_t *buflen,
656		UT_string **err, bool must_exist)
657{
658	int fd;
659	struct stat st;
660
661	if (stat (filename, &st) == -1 || !S_ISREG (st.st_mode)) {
662		if (must_exist) {
663			ucl_create_err (err, "cannot stat file %s: %s",
664					filename, strerror (errno));
665		}
666		return false;
667	}
668	if (st.st_size == 0) {
669		/* Do not map empty files */
670		*buf = "";
671		*buflen = 0;
672	}
673	else {
674		if ((fd = open (filename, O_RDONLY)) == -1) {
675			ucl_create_err (err, "cannot open file %s: %s",
676					filename, strerror (errno));
677			return false;
678		}
679		if ((*buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
680			close (fd);
681			ucl_create_err (err, "cannot mmap file %s: %s",
682					filename, strerror (errno));
683			return false;
684		}
685		*buflen = st.st_size;
686		close (fd);
687	}
688
689	return true;
690}
691
692
693#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
694static inline bool
695ucl_sig_check (const unsigned char *data, size_t datalen,
696		const unsigned char *sig, size_t siglen, struct ucl_parser *parser)
697{
698	struct ucl_pubkey *key;
699	char dig[EVP_MAX_MD_SIZE];
700	unsigned int diglen;
701	EVP_PKEY_CTX *key_ctx;
702	EVP_MD_CTX *sign_ctx = NULL;
703
704	sign_ctx = EVP_MD_CTX_create ();
705
706	LL_FOREACH (parser->keys, key) {
707		key_ctx = EVP_PKEY_CTX_new (key->key, NULL);
708		if (key_ctx != NULL) {
709			if (EVP_PKEY_verify_init (key_ctx) <= 0) {
710				EVP_PKEY_CTX_free (key_ctx);
711				continue;
712			}
713			if (EVP_PKEY_CTX_set_rsa_padding (key_ctx, RSA_PKCS1_PADDING) <= 0) {
714				EVP_PKEY_CTX_free (key_ctx);
715				continue;
716			}
717			if (EVP_PKEY_CTX_set_signature_md (key_ctx, EVP_sha256 ()) <= 0) {
718				EVP_PKEY_CTX_free (key_ctx);
719				continue;
720			}
721			EVP_DigestInit (sign_ctx, EVP_sha256 ());
722			EVP_DigestUpdate (sign_ctx, data, datalen);
723			EVP_DigestFinal (sign_ctx, dig, &diglen);
724
725			if (EVP_PKEY_verify (key_ctx, sig, siglen, dig, diglen) == 1) {
726				EVP_MD_CTX_destroy (sign_ctx);
727				EVP_PKEY_CTX_free (key_ctx);
728				return true;
729			}
730
731			EVP_PKEY_CTX_free (key_ctx);
732		}
733	}
734
735	EVP_MD_CTX_destroy (sign_ctx);
736
737	return false;
738}
739#endif
740
741/**
742 * Include an url to configuration
743 * @param data
744 * @param len
745 * @param parser
746 * @param err
747 * @return
748 */
749static bool
750ucl_include_url (const unsigned char *data, size_t len,
751		struct ucl_parser *parser, bool check_signature, bool must_exist,
752		unsigned priority)
753{
754
755	bool res;
756	unsigned char *buf = NULL;
757	size_t buflen = 0;
758	struct ucl_chunk *chunk;
759	char urlbuf[PATH_MAX];
760	int prev_state;
761
762	snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data);
763
764	if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err, must_exist)) {
765		return (!must_exist || false);
766	}
767
768	if (check_signature) {
769#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
770		unsigned char *sigbuf = NULL;
771		size_t siglen = 0;
772		/* We need to check signature first */
773		snprintf (urlbuf, sizeof (urlbuf), "%.*s.sig", (int)len, data);
774		if (!ucl_fetch_url (urlbuf, &sigbuf, &siglen, &parser->err, true)) {
775			return false;
776		}
777		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
778			ucl_create_err (&parser->err, "cannot verify url %s: %s",
779							urlbuf,
780							ERR_error_string (ERR_get_error (), NULL));
781			if (siglen > 0) {
782				ucl_munmap (sigbuf, siglen);
783			}
784			return false;
785		}
786		if (siglen > 0) {
787			ucl_munmap (sigbuf, siglen);
788		}
789#endif
790	}
791
792	prev_state = parser->state;
793	parser->state = UCL_STATE_INIT;
794
795	res = ucl_parser_add_chunk_priority (parser, buf, buflen, priority);
796	if (res == true) {
797		/* Remove chunk from the stack */
798		chunk = parser->chunks;
799		if (chunk != NULL) {
800			parser->chunks = chunk->next;
801			UCL_FREE (sizeof (struct ucl_chunk), chunk);
802		}
803	}
804
805	parser->state = prev_state;
806	free (buf);
807
808	return res;
809}
810
811/**
812 * Include a single file to the parser
813 * @param data
814 * @param len
815 * @param parser
816 * @param check_signature
817 * @param must_exist
818 * @param allow_glob
819 * @param priority
820 * @return
821 */
822static bool
823ucl_include_file_single (const unsigned char *data, size_t len,
824		struct ucl_parser *parser, bool check_signature, bool must_exist,
825		unsigned priority)
826{
827	bool res;
828	struct ucl_chunk *chunk;
829	unsigned char *buf = NULL;
830	char *old_curfile;
831	size_t buflen;
832	char filebuf[PATH_MAX], realbuf[PATH_MAX];
833	int prev_state;
834	struct ucl_variable *cur_var, *tmp_var, *old_curdir = NULL,
835			*old_filename = NULL;
836
837	snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data);
838	if (ucl_realpath (filebuf, realbuf) == NULL) {
839		if (!must_exist) {
840			return true;
841		}
842		ucl_create_err (&parser->err, "cannot open file %s: %s",
843									filebuf,
844									strerror (errno));
845		return false;
846	}
847
848	if (parser->cur_file && strcmp (realbuf, parser->cur_file) == 0) {
849		/* We are likely including the file itself */
850		ucl_create_err (&parser->err, "trying to include the file %s from itself",
851				realbuf);
852		return false;
853	}
854
855	if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err, must_exist)) {
856		return (!must_exist || false);
857	}
858
859	if (check_signature) {
860#if (defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER >= 0x10000000L)
861		unsigned char *sigbuf = NULL;
862		size_t siglen = 0;
863		/* We need to check signature first */
864		snprintf (filebuf, sizeof (filebuf), "%s.sig", realbuf);
865		if (!ucl_fetch_file (filebuf, &sigbuf, &siglen, &parser->err, true)) {
866			return false;
867		}
868		if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) {
869			ucl_create_err (&parser->err, "cannot verify file %s: %s",
870							filebuf,
871							ERR_error_string (ERR_get_error (), NULL));
872			if (siglen > 0) {
873				ucl_munmap (sigbuf, siglen);
874			}
875			return false;
876		}
877		if (siglen > 0) {
878			ucl_munmap (sigbuf, siglen);
879		}
880#endif
881	}
882
883	old_curfile = parser->cur_file;
884	parser->cur_file = strdup (realbuf);
885
886	/* Store old file vars */
887	DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
888		if (strcmp (cur_var->var, "CURDIR") == 0) {
889			old_curdir = cur_var;
890			DL_DELETE (parser->variables, cur_var);
891		}
892		else if (strcmp (cur_var->var, "FILENAME") == 0) {
893			old_filename = cur_var;
894			DL_DELETE (parser->variables, cur_var);
895		}
896	}
897
898	ucl_parser_set_filevars (parser, realbuf, false);
899
900	prev_state = parser->state;
901	parser->state = UCL_STATE_INIT;
902
903	res = ucl_parser_add_chunk_priority (parser, buf, buflen, priority);
904	if (!res && !must_exist) {
905		/* Free error */
906		utstring_free (parser->err);
907		parser->err = NULL;
908		parser->state = UCL_STATE_AFTER_VALUE;
909	}
910
911	/* Remove chunk from the stack */
912	chunk = parser->chunks;
913	if (chunk != NULL) {
914		parser->chunks = chunk->next;
915		UCL_FREE (sizeof (struct ucl_chunk), chunk);
916		parser->recursion --;
917	}
918
919	/* Restore old file vars */
920	parser->cur_file = old_curfile;
921	DL_FOREACH_SAFE (parser->variables, cur_var, tmp_var) {
922		if (strcmp (cur_var->var, "CURDIR") == 0 && old_curdir) {
923			DL_DELETE (parser->variables, cur_var);
924			free (cur_var->var);
925			free (cur_var->value);
926			UCL_FREE (sizeof (struct ucl_variable), cur_var);
927		}
928		else if (strcmp (cur_var->var, "FILENAME") == 0 && old_filename) {
929			DL_DELETE (parser->variables, cur_var);
930			free (cur_var->var);
931			free (cur_var->value);
932			UCL_FREE (sizeof (struct ucl_variable), cur_var);
933		}
934	}
935	if (old_filename) {
936		DL_APPEND (parser->variables, old_filename);
937	}
938	if (old_curdir) {
939		DL_APPEND (parser->variables, old_curdir);
940	}
941	if (old_curfile) {
942		free (old_curfile);
943	}
944
945	parser->state = prev_state;
946
947	if (buflen > 0) {
948		ucl_munmap (buf, buflen);
949	}
950
951	return res;
952}
953
954/**
955 * Include a file to configuration
956 * @param data
957 * @param len
958 * @param parser
959 * @param err
960 * @return
961 */
962static bool
963ucl_include_file (const unsigned char *data, size_t len,
964		struct ucl_parser *parser, bool check_signature, bool must_exist,
965		bool allow_glob, unsigned priority)
966{
967	const unsigned char *p = data, *end = data + len;
968	bool need_glob = false;
969	int cnt = 0;
970	char glob_pattern[PATH_MAX];
971	size_t i;
972
973#ifndef _WIN32
974	if (!allow_glob) {
975		return ucl_include_file_single (data, len, parser, check_signature,
976			must_exist, priority);
977	}
978	else {
979		/* Check for special symbols in a filename */
980		while (p != end) {
981			if (*p == '*' || *p == '?') {
982				need_glob = true;
983				break;
984			}
985			p ++;
986		}
987		if (need_glob) {
988			glob_t globbuf;
989			memset (&globbuf, 0, sizeof (globbuf));
990			ucl_strlcpy (glob_pattern, (const char *)data, sizeof (glob_pattern));
991			if (glob (glob_pattern, 0, NULL, &globbuf) != 0) {
992				return (!must_exist || false);
993			}
994			for (i = 0; i < globbuf.gl_pathc; i ++) {
995				if (!ucl_include_file_single ((unsigned char *)globbuf.gl_pathv[i],
996						strlen (globbuf.gl_pathv[i]), parser, check_signature,
997						must_exist, priority)) {
998					globfree (&globbuf);
999					return false;
1000				}
1001				cnt ++;
1002			}
1003			globfree (&globbuf);
1004
1005			if (cnt == 0 && must_exist) {
1006				ucl_create_err (&parser->err, "cannot match any files for pattern %s",
1007					glob_pattern);
1008				return false;
1009			}
1010		}
1011		else {
1012			return ucl_include_file_single (data, len, parser, check_signature,
1013				must_exist, priority);
1014		}
1015	}
1016#else
1017	/* Win32 compilers do not support globbing. Therefore, for Win32,
1018	   treat allow_glob/need_glob as a NOOP and just return */
1019	return ucl_include_file_single (data, len, parser, check_signature,
1020		must_exist, priority);
1021#endif
1022
1023	return true;
1024}
1025
1026/**
1027 * Common function to handle .*include* macros
1028 * @param data
1029 * @param len
1030 * @param args
1031 * @param parser
1032 * @param default_try
1033 * @param default_sign
1034 * @return
1035 */
1036static bool
1037ucl_include_common (const unsigned char *data, size_t len,
1038		const ucl_object_t *args, struct ucl_parser *parser,
1039		bool default_try,
1040		bool default_sign)
1041{
1042	bool try_load, allow_glob, allow_url, need_sign;
1043	unsigned priority;
1044	const ucl_object_t *param;
1045	ucl_object_iter_t it = NULL;
1046
1047	/* Default values */
1048	try_load = default_try;
1049	allow_glob = false;
1050	allow_url = true;
1051	need_sign = default_sign;
1052	priority = 0;
1053
1054	/* Process arguments */
1055	if (args != NULL && args->type == UCL_OBJECT) {
1056		while ((param = ucl_iterate_object (args, &it, true)) != NULL) {
1057			if (param->type == UCL_BOOLEAN) {
1058				if (strcmp (param->key, "try") == 0) {
1059					try_load = ucl_object_toboolean (param);
1060				}
1061				else if (strcmp (param->key, "sign") == 0) {
1062					need_sign = ucl_object_toboolean (param);
1063				}
1064				else if (strcmp (param->key, "glob") == 0) {
1065					allow_glob =  ucl_object_toboolean (param);
1066				}
1067				else if (strcmp (param->key, "url") == 0) {
1068					allow_url =  ucl_object_toboolean (param);
1069				}
1070			}
1071			else if (param->type == UCL_INT) {
1072				if (strcmp (param->key, "priority") == 0) {
1073					priority = ucl_object_toint (param);
1074				}
1075			}
1076		}
1077	}
1078
1079	if (*data == '/' || *data == '.') {
1080		/* Try to load a file */
1081		return ucl_include_file (data, len, parser, need_sign, !try_load,
1082				allow_glob, priority);
1083	}
1084	else if (allow_url) {
1085		/* Globbing is not used for URL's */
1086		return ucl_include_url (data, len, parser, need_sign, !try_load,
1087				priority);
1088	}
1089
1090	return false;
1091}
1092
1093/**
1094 * Handle include macro
1095 * @param data include data
1096 * @param len length of data
1097 * @param ud user data
1098 * @param err error ptr
1099 * @return
1100 */
1101UCL_EXTERN bool
1102ucl_include_handler (const unsigned char *data, size_t len,
1103		const ucl_object_t *args, void* ud)
1104{
1105	struct ucl_parser *parser = ud;
1106
1107	return ucl_include_common (data, len, args, parser, false, false);
1108}
1109
1110/**
1111 * Handle includes macro
1112 * @param data include data
1113 * @param len length of data
1114 * @param ud user data
1115 * @param err error ptr
1116 * @return
1117 */
1118UCL_EXTERN bool
1119ucl_includes_handler (const unsigned char *data, size_t len,
1120		const ucl_object_t *args, void* ud)
1121{
1122	struct ucl_parser *parser = ud;
1123
1124	return ucl_include_common (data, len, args, parser, false, true);
1125}
1126
1127
1128UCL_EXTERN bool
1129ucl_try_include_handler (const unsigned char *data, size_t len,
1130		const ucl_object_t *args, void* ud)
1131{
1132	struct ucl_parser *parser = ud;
1133
1134	return ucl_include_common (data, len, args, parser, true, false);
1135}
1136
1137UCL_EXTERN bool
1138ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand)
1139{
1140	char realbuf[PATH_MAX], *curdir;
1141
1142	if (filename != NULL) {
1143		if (need_expand) {
1144			if (ucl_realpath (filename, realbuf) == NULL) {
1145				return false;
1146			}
1147		}
1148		else {
1149			ucl_strlcpy (realbuf, filename, sizeof (realbuf));
1150		}
1151
1152		/* Define variables */
1153		ucl_parser_register_variable (parser, "FILENAME", realbuf);
1154		curdir = dirname (realbuf);
1155		ucl_parser_register_variable (parser, "CURDIR", curdir);
1156	}
1157	else {
1158		/* Set everything from the current dir */
1159		curdir = getcwd (realbuf, sizeof (realbuf));
1160		ucl_parser_register_variable (parser, "FILENAME", "undef");
1161		ucl_parser_register_variable (parser, "CURDIR", curdir);
1162	}
1163
1164	return true;
1165}
1166
1167UCL_EXTERN bool
1168ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
1169{
1170	unsigned char *buf;
1171	size_t len;
1172	bool ret;
1173	char realbuf[PATH_MAX];
1174
1175	if (ucl_realpath (filename, realbuf) == NULL) {
1176		ucl_create_err (&parser->err, "cannot open file %s: %s",
1177				filename,
1178				strerror (errno));
1179		return false;
1180	}
1181
1182	if (!ucl_fetch_file (realbuf, &buf, &len, &parser->err, true)) {
1183		return false;
1184	}
1185
1186	if (parser->cur_file) {
1187		free (parser->cur_file);
1188	}
1189	parser->cur_file = strdup (realbuf);
1190	ucl_parser_set_filevars (parser, realbuf, false);
1191	ret = ucl_parser_add_chunk (parser, buf, len);
1192
1193	if (len > 0) {
1194		ucl_munmap (buf, len);
1195	}
1196
1197	return ret;
1198}
1199
1200UCL_EXTERN bool
1201ucl_parser_add_fd (struct ucl_parser *parser, int fd)
1202{
1203	unsigned char *buf;
1204	size_t len;
1205	bool ret;
1206	struct stat st;
1207
1208	if (fstat (fd, &st) == -1) {
1209		ucl_create_err (&parser->err, "cannot stat fd %d: %s",
1210			fd, strerror (errno));
1211		return false;
1212	}
1213	if ((buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
1214		ucl_create_err (&parser->err, "cannot mmap fd %d: %s",
1215			fd, strerror (errno));
1216		return false;
1217	}
1218
1219	if (parser->cur_file) {
1220		free (parser->cur_file);
1221	}
1222	parser->cur_file = NULL;
1223	len = st.st_size;
1224	ret = ucl_parser_add_chunk (parser, buf, len);
1225
1226	if (len > 0) {
1227		ucl_munmap (buf, len);
1228	}
1229
1230	return ret;
1231}
1232
1233size_t
1234ucl_strlcpy (char *dst, const char *src, size_t siz)
1235{
1236	char *d = dst;
1237	const char *s = src;
1238	size_t n = siz;
1239
1240	/* Copy as many bytes as will fit */
1241	if (n != 0) {
1242		while (--n != 0) {
1243			if ((*d++ = *s++) == '\0') {
1244				break;
1245			}
1246		}
1247	}
1248
1249	if (n == 0 && siz != 0) {
1250		*d = '\0';
1251	}
1252
1253	return (s - src - 1);    /* count does not include NUL */
1254}
1255
1256size_t
1257ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz)
1258{
1259	memcpy (dst, src, siz - 1);
1260	dst[siz - 1] = '\0';
1261
1262	return siz - 1;
1263}
1264
1265size_t
1266ucl_strlcpy_tolower (char *dst, const char *src, size_t siz)
1267{
1268	char *d = dst;
1269	const char *s = src;
1270	size_t n = siz;
1271
1272	/* Copy as many bytes as will fit */
1273	if (n != 0) {
1274		while (--n != 0) {
1275			if ((*d++ = tolower (*s++)) == '\0') {
1276				break;
1277			}
1278		}
1279	}
1280
1281	if (n == 0 && siz != 0) {
1282		*d = '\0';
1283	}
1284
1285	return (s - src);    /* count does not include NUL */
1286}
1287
1288ucl_object_t *
1289ucl_object_fromstring_common (const char *str, size_t len, enum ucl_string_flags flags)
1290{
1291	ucl_object_t *obj;
1292	const char *start, *end, *p, *pos;
1293	char *dst, *d;
1294	size_t escaped_len;
1295
1296	if (str == NULL) {
1297		return NULL;
1298	}
1299
1300	obj = ucl_object_new ();
1301	if (obj) {
1302		if (len == 0) {
1303			len = strlen (str);
1304		}
1305		if (flags & UCL_STRING_TRIM) {
1306			/* Skip leading spaces */
1307			for (start = str; (size_t)(start - str) < len; start ++) {
1308				if (!ucl_test_character (*start, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
1309					break;
1310				}
1311			}
1312			/* Skip trailing spaces */
1313			for (end = str + len - 1; end > start; end --) {
1314				if (!ucl_test_character (*end, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
1315					break;
1316				}
1317			}
1318			end ++;
1319		}
1320		else {
1321			start = str;
1322			end = str + len;
1323		}
1324
1325		obj->type = UCL_STRING;
1326		if (flags & UCL_STRING_ESCAPE) {
1327			for (p = start, escaped_len = 0; p < end; p ++, escaped_len ++) {
1328				if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
1329					escaped_len ++;
1330				}
1331			}
1332			dst = malloc (escaped_len + 1);
1333			if (dst != NULL) {
1334				for (p = start, d = dst; p < end; p ++, d ++) {
1335					if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
1336						switch (*p) {
1337						case '\n':
1338							*d++ = '\\';
1339							*d = 'n';
1340							break;
1341						case '\r':
1342							*d++ = '\\';
1343							*d = 'r';
1344							break;
1345						case '\b':
1346							*d++ = '\\';
1347							*d = 'b';
1348							break;
1349						case '\t':
1350							*d++ = '\\';
1351							*d = 't';
1352							break;
1353						case '\f':
1354							*d++ = '\\';
1355							*d = 'f';
1356							break;
1357						case '\\':
1358							*d++ = '\\';
1359							*d = '\\';
1360							break;
1361						case '"':
1362							*d++ = '\\';
1363							*d = '"';
1364							break;
1365						}
1366					}
1367					else {
1368						*d = *p;
1369					}
1370				}
1371				*d = '\0';
1372				obj->value.sv = dst;
1373				obj->trash_stack[UCL_TRASH_VALUE] = dst;
1374				obj->len = escaped_len;
1375			}
1376		}
1377		else {
1378			dst = malloc (end - start + 1);
1379			if (dst != NULL) {
1380				ucl_strlcpy_unsafe (dst, start, end - start + 1);
1381				obj->value.sv = dst;
1382				obj->trash_stack[UCL_TRASH_VALUE] = dst;
1383				obj->len = end - start;
1384			}
1385		}
1386		if ((flags & UCL_STRING_PARSE) && dst != NULL) {
1387			/* Parse what we have */
1388			if (flags & UCL_STRING_PARSE_BOOLEAN) {
1389				if (!ucl_maybe_parse_boolean (obj, dst, obj->len) && (flags & UCL_STRING_PARSE_NUMBER)) {
1390					ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1391							flags & UCL_STRING_PARSE_DOUBLE,
1392							flags & UCL_STRING_PARSE_BYTES,
1393							flags & UCL_STRING_PARSE_TIME);
1394				}
1395			}
1396			else {
1397				ucl_maybe_parse_number (obj, dst, dst + obj->len, &pos,
1398						flags & UCL_STRING_PARSE_DOUBLE,
1399						flags & UCL_STRING_PARSE_BYTES,
1400						flags & UCL_STRING_PARSE_TIME);
1401			}
1402		}
1403	}
1404
1405	return obj;
1406}
1407
1408static bool
1409ucl_object_insert_key_common (ucl_object_t *top, ucl_object_t *elt,
1410		const char *key, size_t keylen, bool copy_key, bool merge, bool replace)
1411{
1412	ucl_object_t *found, *tmp;
1413	const ucl_object_t *cur;
1414	ucl_object_iter_t it = NULL;
1415	const char *p;
1416	int ret = true;
1417
1418	if (elt == NULL || key == NULL) {
1419		return false;
1420	}
1421
1422	if (top == NULL) {
1423		return false;
1424	}
1425
1426	if (top->type != UCL_OBJECT) {
1427		/* It is possible to convert NULL type to an object */
1428		if (top->type == UCL_NULL) {
1429			top->type = UCL_OBJECT;
1430		}
1431		else {
1432			/* Refuse converting of other object types */
1433			return false;
1434		}
1435	}
1436
1437	if (top->value.ov == NULL) {
1438		top->value.ov = ucl_hash_create (false);
1439	}
1440
1441	if (keylen == 0) {
1442		keylen = strlen (key);
1443	}
1444
1445	for (p = key; p < key + keylen; p ++) {
1446		if (ucl_test_character (*p, UCL_CHARACTER_UCL_UNSAFE)) {
1447			elt->flags |= UCL_OBJECT_NEED_KEY_ESCAPE;
1448			break;
1449		}
1450	}
1451
1452	/* workaround for some use cases */
1453	if (elt->trash_stack[UCL_TRASH_KEY] != NULL &&
1454			key != (const char *)elt->trash_stack[UCL_TRASH_KEY]) {
1455		/* Remove copied key */
1456		free (elt->trash_stack[UCL_TRASH_KEY]);
1457		elt->trash_stack[UCL_TRASH_KEY] = NULL;
1458		elt->flags &= ~UCL_OBJECT_ALLOCATED_KEY;
1459	}
1460
1461	elt->key = key;
1462	elt->keylen = keylen;
1463
1464	if (copy_key) {
1465		ucl_copy_key_trash (elt);
1466	}
1467
1468	found = __DECONST (ucl_object_t *, ucl_hash_search_obj (top->value.ov, elt));
1469
1470	if (found == NULL) {
1471		top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false);
1472		top->len ++;
1473		if (replace) {
1474			ret = false;
1475		}
1476	}
1477	else {
1478		if (replace) {
1479			ucl_hash_replace (top->value.ov, found, elt);
1480			ucl_object_unref (found);
1481		}
1482		else if (merge) {
1483			if (found->type != UCL_OBJECT && elt->type == UCL_OBJECT) {
1484				/* Insert old elt to new one */
1485				ucl_object_insert_key_common (elt, found, found->key,
1486						found->keylen, copy_key, false, false);
1487				ucl_hash_delete (top->value.ov, found);
1488				top->value.ov = ucl_hash_insert_object (top->value.ov, elt, false);
1489			}
1490			else if (found->type == UCL_OBJECT && elt->type != UCL_OBJECT) {
1491				/* Insert new to old */
1492				ucl_object_insert_key_common (found, elt, elt->key,
1493						elt->keylen, copy_key, false, false);
1494			}
1495			else if (found->type == UCL_OBJECT && elt->type == UCL_OBJECT) {
1496				/* Mix two hashes */
1497				while ((cur = ucl_iterate_object (elt, &it, true)) != NULL) {
1498					tmp = ucl_object_ref (cur);
1499					ucl_object_insert_key_common (found, tmp, cur->key,
1500							cur->keylen, copy_key, false, false);
1501				}
1502				ucl_object_unref (elt);
1503			}
1504			else {
1505				/* Just make a list of scalars */
1506				DL_APPEND (found, elt);
1507			}
1508		}
1509		else {
1510			DL_APPEND (found, elt);
1511		}
1512	}
1513
1514	return ret;
1515}
1516
1517bool
1518ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen)
1519{
1520	ucl_object_t *found;
1521
1522	if (top == NULL || key == NULL) {
1523		return false;
1524	}
1525
1526	found = __DECONST (ucl_object_t *, ucl_object_find_keyl (top, key, keylen));
1527
1528	if (found == NULL) {
1529		return false;
1530	}
1531
1532	ucl_hash_delete (top->value.ov, found);
1533	ucl_object_unref (found);
1534	top->len --;
1535
1536	return true;
1537}
1538
1539bool
1540ucl_object_delete_key (ucl_object_t *top, const char *key)
1541{
1542	return ucl_object_delete_keyl (top, key, strlen(key));
1543}
1544
1545ucl_object_t*
1546ucl_object_pop_keyl (ucl_object_t *top, const char *key, size_t keylen)
1547{
1548	const ucl_object_t *found;
1549
1550	if (top == NULL || key == NULL) {
1551		return false;
1552	}
1553	found = ucl_object_find_keyl (top, key, keylen);
1554
1555	if (found == NULL) {
1556		return NULL;
1557	}
1558	ucl_hash_delete (top->value.ov, found);
1559	top->len --;
1560
1561	return __DECONST (ucl_object_t *, found);
1562}
1563
1564ucl_object_t*
1565ucl_object_pop_key (ucl_object_t *top, const char *key)
1566{
1567	return ucl_object_pop_keyl (top, key, strlen(key));
1568}
1569
1570bool
1571ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
1572		const char *key, size_t keylen, bool copy_key)
1573{
1574	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, false);
1575}
1576
1577bool
1578ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
1579		const char *key, size_t keylen, bool copy_key)
1580{
1581	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, true, false);
1582}
1583
1584bool
1585ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
1586		const char *key, size_t keylen, bool copy_key)
1587{
1588	return ucl_object_insert_key_common (top, elt, key, keylen, copy_key, false, true);
1589}
1590
1591bool
1592ucl_object_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
1593{
1594	ucl_object_t *cur = NULL, *cp = NULL, *found = NULL;
1595	ucl_object_iter_t iter = NULL;
1596
1597	if (top == NULL || top->type != UCL_OBJECT || elt == NULL || elt->type != UCL_OBJECT) {
1598		return false;
1599	}
1600
1601	/* Mix two hashes */
1602	while ((cur = (ucl_object_t*)ucl_hash_iterate (elt->value.ov, &iter))) {
1603		if (copy) {
1604			cp = ucl_object_copy (cur);
1605		}
1606		else {
1607			cp = ucl_object_ref (cur);
1608		}
1609		found = __DECONST(ucl_object_t *, ucl_hash_search (top->value.ov, cp->key, cp->keylen));
1610		if (found == NULL) {
1611			/* The key does not exist */
1612			top->value.ov = ucl_hash_insert_object (top->value.ov, cp, false);
1613			top->len ++;
1614		}
1615		else {
1616			/* The key already exists, replace it */
1617			ucl_hash_replace (top->value.ov, found, cp);
1618			ucl_object_unref (found);
1619		}
1620	}
1621
1622	return true;
1623}
1624
1625const ucl_object_t *
1626ucl_object_find_keyl (const ucl_object_t *obj, const char *key, size_t klen)
1627{
1628	const ucl_object_t *ret;
1629	ucl_object_t srch;
1630
1631	if (obj == NULL || obj->type != UCL_OBJECT || key == NULL) {
1632		return NULL;
1633	}
1634
1635	srch.key = key;
1636	srch.keylen = klen;
1637	ret = ucl_hash_search_obj (obj->value.ov, &srch);
1638
1639	return ret;
1640}
1641
1642const ucl_object_t *
1643ucl_object_find_key (const ucl_object_t *obj, const char *key)
1644{
1645	if (key == NULL)
1646		return NULL;
1647
1648	return ucl_object_find_keyl (obj, key, strlen(key));
1649}
1650
1651const ucl_object_t*
1652ucl_iterate_object (const ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values)
1653{
1654	const ucl_object_t *elt = NULL;
1655
1656	if (obj == NULL || iter == NULL) {
1657		return NULL;
1658	}
1659
1660	if (expand_values) {
1661		switch (obj->type) {
1662		case UCL_OBJECT:
1663			return (const ucl_object_t*)ucl_hash_iterate (obj->value.ov, iter);
1664			break;
1665		case UCL_ARRAY: {
1666			unsigned int idx;
1667			UCL_ARRAY_GET (vec, obj);
1668			idx = (unsigned int)(uintptr_t)(*iter);
1669
1670			if (vec != NULL) {
1671				while (idx < kv_size (*vec)) {
1672					if ((elt = kv_A (*vec, idx)) != NULL) {
1673						idx ++;
1674						break;
1675					}
1676					idx ++;
1677				}
1678				*iter = (void *)(uintptr_t)idx;
1679			}
1680
1681			return elt;
1682			break;
1683		}
1684		default:
1685			/* Go to linear iteration */
1686			break;
1687		}
1688	}
1689	/* Treat everything as a linear list */
1690	elt = *iter;
1691	if (elt == NULL) {
1692		elt = obj;
1693	}
1694	else if (elt == obj) {
1695		return NULL;
1696	}
1697	*iter = __DECONST (void *, elt->next ? elt->next : obj);
1698	return elt;
1699
1700	/* Not reached */
1701	return NULL;
1702}
1703
1704const char safe_iter_magic[4] = {'u', 'i', 't', 'e'};
1705struct ucl_object_safe_iter {
1706	char magic[4]; /* safety check */
1707	const ucl_object_t *impl_it; /* implicit object iteration */
1708	ucl_object_iter_t expl_it; /* explicit iteration */
1709};
1710
1711#define UCL_SAFE_ITER(ptr) (struct ucl_object_safe_iter *)(ptr)
1712#define UCL_SAFE_ITER_CHECK(it) do { \
1713	assert (it != NULL); \
1714	assert (memcmp (it->magic, safe_iter_magic, sizeof (it->magic)) == 0); \
1715 } while (0)
1716
1717ucl_object_iter_t
1718ucl_object_iterate_new (const ucl_object_t *obj)
1719{
1720	struct ucl_object_safe_iter *it;
1721
1722	it = UCL_ALLOC (sizeof (*it));
1723	if (it != NULL) {
1724		memcpy (it->magic, safe_iter_magic, sizeof (it->magic));
1725		it->expl_it = NULL;
1726		it->impl_it = obj;
1727	}
1728
1729	return (ucl_object_iter_t)it;
1730}
1731
1732
1733ucl_object_iter_t
1734ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj)
1735{
1736	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
1737
1738	UCL_SAFE_ITER_CHECK (rit);
1739
1740	rit->impl_it = obj;
1741	rit->expl_it = NULL;
1742
1743	return it;
1744}
1745
1746const ucl_object_t*
1747ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values)
1748{
1749	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
1750	const ucl_object_t *ret = NULL;
1751
1752	UCL_SAFE_ITER_CHECK (rit);
1753
1754	if (rit->impl_it == NULL) {
1755		return NULL;
1756	}
1757
1758	if (rit->impl_it->type == UCL_OBJECT || rit->impl_it->type == UCL_ARRAY) {
1759		ret = ucl_iterate_object (rit->impl_it, &rit->expl_it, true);
1760
1761		if (ret == NULL) {
1762			/* Need to switch to another implicit object in chain */
1763			rit->impl_it = rit->impl_it->next;
1764			rit->expl_it = NULL;
1765			return ucl_object_iterate_safe (it, expand_values);
1766		}
1767	}
1768	else {
1769		/* Just iterate over the implicit array */
1770		ret = rit->impl_it;
1771		rit->impl_it = rit->impl_it->next;
1772		if (expand_values) {
1773			/* We flatten objects if need to expand values */
1774			if (ret->type == UCL_OBJECT || ret->type == UCL_ARRAY) {
1775				return ucl_object_iterate_safe (it, expand_values);
1776			}
1777		}
1778	}
1779
1780	return ret;
1781}
1782
1783void
1784ucl_object_iterate_free (ucl_object_iter_t it)
1785{
1786	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
1787
1788	UCL_SAFE_ITER_CHECK (rit);
1789
1790	UCL_FREE (sizeof (*rit), it);
1791}
1792
1793const ucl_object_t *
1794ucl_lookup_path (const ucl_object_t *top, const char *path_in) {
1795	const ucl_object_t *o = NULL, *found;
1796	const char *p, *c;
1797	char *err_str;
1798	unsigned index;
1799
1800	if (path_in == NULL || top == NULL) {
1801		return NULL;
1802	}
1803
1804	found = NULL;
1805	p = path_in;
1806
1807	/* Skip leading dots */
1808	while (*p == '.') {
1809		p ++;
1810	}
1811
1812	c = p;
1813	while (*p != '\0') {
1814		p ++;
1815		if (*p == '.' || *p == '\0') {
1816			if (p > c) {
1817				switch (top->type) {
1818				case UCL_ARRAY:
1819					/* Key should be an int */
1820					index = strtoul (c, &err_str, 10);
1821					if (err_str != NULL && (*err_str != '.' && *err_str != '\0')) {
1822						return NULL;
1823					}
1824					o = ucl_array_find_index (top, index);
1825					break;
1826				default:
1827					o = ucl_object_find_keyl (top, c, p - c);
1828					break;
1829				}
1830				if (o == NULL) {
1831					return NULL;
1832				}
1833				top = o;
1834			}
1835			if (*p != '\0') {
1836				c = p + 1;
1837			}
1838		}
1839	}
1840	found = o;
1841
1842	return found;
1843}
1844
1845
1846ucl_object_t *
1847ucl_object_new (void)
1848{
1849	return ucl_object_typed_new (UCL_NULL);
1850}
1851
1852ucl_object_t *
1853ucl_object_typed_new (ucl_type_t type)
1854{
1855	return ucl_object_new_full (type, 0);
1856}
1857
1858ucl_object_t *
1859ucl_object_new_full (ucl_type_t type, unsigned priority)
1860{
1861	ucl_object_t *new;
1862
1863	if (type != UCL_USERDATA) {
1864		new = UCL_ALLOC (sizeof (ucl_object_t));
1865		if (new != NULL) {
1866			memset (new, 0, sizeof (ucl_object_t));
1867			new->ref = 1;
1868			new->type = (type <= UCL_NULL ? type : UCL_NULL);
1869			new->next = NULL;
1870			new->prev = new;
1871			ucl_object_set_priority (new, priority);
1872
1873			if (type == UCL_ARRAY) {
1874				new->value.av = UCL_ALLOC (sizeof (ucl_array_t));
1875				if (new->value.av) {
1876					memset (new->value.av, 0, sizeof (ucl_array_t));
1877					UCL_ARRAY_GET (vec, new);
1878
1879					/* Preallocate some space for arrays */
1880					kv_resize (ucl_object_t *, *vec, 8);
1881				}
1882			}
1883		}
1884	}
1885	else {
1886		new = ucl_object_new_userdata (NULL, NULL);
1887		ucl_object_set_priority (new, priority);
1888	}
1889
1890	return new;
1891}
1892
1893ucl_object_t*
1894ucl_object_new_userdata (ucl_userdata_dtor dtor, ucl_userdata_emitter emitter)
1895{
1896	struct ucl_object_userdata *new;
1897	size_t nsize = sizeof (*new);
1898
1899	new = UCL_ALLOC (nsize);
1900	if (new != NULL) {
1901		memset (new, 0, nsize);
1902		new->obj.ref = 1;
1903		new->obj.type = UCL_USERDATA;
1904		new->obj.next = NULL;
1905		new->obj.prev = (ucl_object_t *)new;
1906		new->dtor = dtor;
1907		new->emitter = emitter;
1908	}
1909
1910	return (ucl_object_t *)new;
1911}
1912
1913ucl_type_t
1914ucl_object_type (const ucl_object_t *obj)
1915{
1916	return obj->type;
1917}
1918
1919ucl_object_t*
1920ucl_object_fromstring (const char *str)
1921{
1922	return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
1923}
1924
1925ucl_object_t *
1926ucl_object_fromlstring (const char *str, size_t len)
1927{
1928	return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
1929}
1930
1931ucl_object_t *
1932ucl_object_fromint (int64_t iv)
1933{
1934	ucl_object_t *obj;
1935
1936	obj = ucl_object_new ();
1937	if (obj != NULL) {
1938		obj->type = UCL_INT;
1939		obj->value.iv = iv;
1940	}
1941
1942	return obj;
1943}
1944
1945ucl_object_t *
1946ucl_object_fromdouble (double dv)
1947{
1948	ucl_object_t *obj;
1949
1950	obj = ucl_object_new ();
1951	if (obj != NULL) {
1952		obj->type = UCL_FLOAT;
1953		obj->value.dv = dv;
1954	}
1955
1956	return obj;
1957}
1958
1959ucl_object_t*
1960ucl_object_frombool (bool bv)
1961{
1962	ucl_object_t *obj;
1963
1964	obj = ucl_object_new ();
1965	if (obj != NULL) {
1966		obj->type = UCL_BOOLEAN;
1967		obj->value.iv = bv;
1968	}
1969
1970	return obj;
1971}
1972
1973bool
1974ucl_array_append (ucl_object_t *top, ucl_object_t *elt)
1975{
1976	UCL_ARRAY_GET (vec, top);
1977
1978	if (elt == NULL || top == NULL) {
1979		return false;
1980	}
1981
1982	if (vec == NULL) {
1983		vec = UCL_ALLOC (sizeof (*vec));
1984		kv_init (*vec);
1985		top->value.av = (void *)vec;
1986	}
1987
1988	kv_push (ucl_object_t *, *vec, elt);
1989
1990	top->len ++;
1991
1992	return true;
1993}
1994
1995bool
1996ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
1997{
1998	UCL_ARRAY_GET (vec, top);
1999
2000	if (elt == NULL || top == NULL) {
2001		return false;
2002	}
2003
2004	if (vec == NULL) {
2005		vec = UCL_ALLOC (sizeof (*vec));
2006		kv_init (*vec);
2007		top->value.av = (void *)vec;
2008		kv_push (ucl_object_t *, *vec, elt);
2009	}
2010	else {
2011		/* Slow O(n) algorithm */
2012		kv_prepend (ucl_object_t *, *vec, elt);
2013	}
2014
2015	top->len ++;
2016
2017	return true;
2018}
2019
2020bool
2021ucl_array_merge (ucl_object_t *top, ucl_object_t *elt, bool copy)
2022{
2023	unsigned i;
2024	ucl_object_t **obj;
2025	UCL_ARRAY_GET (v1, top);
2026	UCL_ARRAY_GET (v2, elt);
2027
2028	if (elt == NULL || top == NULL || top->type != UCL_ARRAY || elt->type != UCL_ARRAY) {
2029		return false;
2030	}
2031
2032	kv_concat (ucl_object_t *, *v1, *v2);
2033
2034	for (i = v2->n; i < v1->n; i ++) {
2035		obj = &kv_A (*v1, i);
2036		if (*obj == NULL) {
2037			continue;
2038		}
2039
2040		top->len ++;
2041		if (copy) {
2042			*obj = ucl_object_copy (*obj);
2043		}
2044		else {
2045			ucl_object_ref (*obj);
2046		}
2047	}
2048
2049	return true;
2050}
2051
2052ucl_object_t *
2053ucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
2054{
2055	UCL_ARRAY_GET (vec, top);
2056	ucl_object_t *ret = NULL;
2057	unsigned i;
2058
2059	for (i = 0; i < vec->n; i ++) {
2060		if (kv_A (*vec, i) == elt) {
2061			kv_del (ucl_object_t *, *vec, i);
2062			ret = elt;
2063			top->len --;
2064			break;
2065		}
2066	}
2067
2068	return ret;
2069}
2070
2071const ucl_object_t *
2072ucl_array_head (const ucl_object_t *top)
2073{
2074	UCL_ARRAY_GET (vec, top);
2075
2076	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
2077		return NULL;
2078	}
2079
2080	return (vec->n > 0 ? vec->a[0] : NULL);
2081}
2082
2083const ucl_object_t *
2084ucl_array_tail (const ucl_object_t *top)
2085{
2086	UCL_ARRAY_GET (vec, top);
2087
2088	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
2089		return NULL;
2090	}
2091
2092	return (vec->n > 0 ? vec->a[vec->n - 1] : NULL);
2093}
2094
2095ucl_object_t *
2096ucl_array_pop_last (ucl_object_t *top)
2097{
2098	UCL_ARRAY_GET (vec, top);
2099	ucl_object_t **obj, *ret = NULL;
2100
2101	if (vec != NULL && vec->n > 0) {
2102		obj = &kv_A (*vec, vec->n - 1);
2103		ret = *obj;
2104		kv_del (ucl_object_t *, *vec, vec->n - 1);
2105		top->len --;
2106	}
2107
2108	return ret;
2109}
2110
2111ucl_object_t *
2112ucl_array_pop_first (ucl_object_t *top)
2113{
2114	UCL_ARRAY_GET (vec, top);
2115	ucl_object_t **obj, *ret = NULL;
2116
2117	if (vec != NULL && vec->n > 0) {
2118		obj = &kv_A (*vec, 0);
2119		ret = *obj;
2120		kv_del (ucl_object_t *, *vec, 0);
2121		top->len --;
2122	}
2123
2124	return ret;
2125}
2126
2127const ucl_object_t *
2128ucl_array_find_index (const ucl_object_t *top, unsigned int index)
2129{
2130	UCL_ARRAY_GET (vec, top);
2131
2132	if (vec != NULL && vec->n > 0 && index < vec->n) {
2133		return kv_A (*vec, index);
2134	}
2135
2136	return NULL;
2137}
2138
2139ucl_object_t *
2140ucl_array_replace_index (ucl_object_t *top, ucl_object_t *elt,
2141	unsigned int index)
2142{
2143	UCL_ARRAY_GET (vec, top);
2144	ucl_object_t *ret = NULL;
2145
2146	if (vec != NULL && vec->n > 0 && index < vec->n) {
2147		ret = kv_A (*vec, index);
2148		kv_A (*vec, index) = elt;
2149	}
2150
2151	return ret;
2152}
2153
2154ucl_object_t *
2155ucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
2156{
2157
2158	if (head == NULL) {
2159		elt->next = NULL;
2160		elt->prev = elt;
2161		head = elt;
2162	}
2163	else {
2164		elt->prev = head->prev;
2165		head->prev->next = elt;
2166		head->prev = elt;
2167		elt->next = NULL;
2168	}
2169
2170	return head;
2171}
2172
2173bool
2174ucl_object_todouble_safe (const ucl_object_t *obj, double *target)
2175{
2176	if (obj == NULL || target == NULL) {
2177		return false;
2178	}
2179	switch (obj->type) {
2180	case UCL_INT:
2181		*target = obj->value.iv; /* Probaly could cause overflow */
2182		break;
2183	case UCL_FLOAT:
2184	case UCL_TIME:
2185		*target = obj->value.dv;
2186		break;
2187	default:
2188		return false;
2189	}
2190
2191	return true;
2192}
2193
2194double
2195ucl_object_todouble (const ucl_object_t *obj)
2196{
2197	double result = 0.;
2198
2199	ucl_object_todouble_safe (obj, &result);
2200	return result;
2201}
2202
2203bool
2204ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target)
2205{
2206	if (obj == NULL || target == NULL) {
2207		return false;
2208	}
2209	switch (obj->type) {
2210	case UCL_INT:
2211		*target = obj->value.iv;
2212		break;
2213	case UCL_FLOAT:
2214	case UCL_TIME:
2215		*target = obj->value.dv; /* Loosing of decimal points */
2216		break;
2217	default:
2218		return false;
2219	}
2220
2221	return true;
2222}
2223
2224int64_t
2225ucl_object_toint (const ucl_object_t *obj)
2226{
2227	int64_t result = 0;
2228
2229	ucl_object_toint_safe (obj, &result);
2230	return result;
2231}
2232
2233bool
2234ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target)
2235{
2236	if (obj == NULL || target == NULL) {
2237		return false;
2238	}
2239	switch (obj->type) {
2240	case UCL_BOOLEAN:
2241		*target = (obj->value.iv == true);
2242		break;
2243	default:
2244		return false;
2245	}
2246
2247	return true;
2248}
2249
2250bool
2251ucl_object_toboolean (const ucl_object_t *obj)
2252{
2253	bool result = false;
2254
2255	ucl_object_toboolean_safe (obj, &result);
2256	return result;
2257}
2258
2259bool
2260ucl_object_tostring_safe (const ucl_object_t *obj, const char **target)
2261{
2262	if (obj == NULL || target == NULL) {
2263		return false;
2264	}
2265
2266	switch (obj->type) {
2267	case UCL_STRING:
2268		*target = ucl_copy_value_trash (obj);
2269		break;
2270	default:
2271		return false;
2272	}
2273
2274	return true;
2275}
2276
2277const char *
2278ucl_object_tostring (const ucl_object_t *obj)
2279{
2280	const char *result = NULL;
2281
2282	ucl_object_tostring_safe (obj, &result);
2283	return result;
2284}
2285
2286const char *
2287ucl_object_tostring_forced (const ucl_object_t *obj)
2288{
2289	return ucl_copy_value_trash (obj);
2290}
2291
2292bool
2293ucl_object_tolstring_safe (const ucl_object_t *obj, const char **target, size_t *tlen)
2294{
2295	if (obj == NULL || target == NULL) {
2296		return false;
2297	}
2298	switch (obj->type) {
2299	case UCL_STRING:
2300		*target = obj->value.sv;
2301		if (tlen != NULL) {
2302			*tlen = obj->len;
2303		}
2304		break;
2305	default:
2306		return false;
2307	}
2308
2309	return true;
2310}
2311
2312const char *
2313ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen)
2314{
2315	const char *result = NULL;
2316
2317	ucl_object_tolstring_safe (obj, &result, tlen);
2318	return result;
2319}
2320
2321const char *
2322ucl_object_key (const ucl_object_t *obj)
2323{
2324	return ucl_copy_key_trash (obj);
2325}
2326
2327const char *
2328ucl_object_keyl (const ucl_object_t *obj, size_t *len)
2329{
2330	if (len == NULL || obj == NULL) {
2331		return NULL;
2332	}
2333	*len = obj->keylen;
2334	return obj->key;
2335}
2336
2337ucl_object_t *
2338ucl_object_ref (const ucl_object_t *obj)
2339{
2340	ucl_object_t *res = NULL;
2341
2342	if (obj != NULL) {
2343		if (obj->flags & UCL_OBJECT_EPHEMERAL) {
2344			/*
2345			 * Use deep copy for ephemeral objects, note that its refcount
2346			 * is NOT increased, since ephemeral objects does not need refcount
2347			 * at all
2348			 */
2349			res = ucl_object_copy (obj);
2350		}
2351		else {
2352			res = __DECONST (ucl_object_t *, obj);
2353#ifdef HAVE_ATOMIC_BUILTINS
2354			(void)__sync_add_and_fetch (&res->ref, 1);
2355#else
2356			res->ref ++;
2357#endif
2358		}
2359	}
2360	return res;
2361}
2362
2363static ucl_object_t *
2364ucl_object_copy_internal (const ucl_object_t *other, bool allow_array)
2365{
2366
2367	ucl_object_t *new;
2368	ucl_object_iter_t it = NULL;
2369	const ucl_object_t *cur;
2370
2371	new = malloc (sizeof (*new));
2372
2373	if (new != NULL) {
2374		memcpy (new, other, sizeof (*new));
2375		if (other->flags & UCL_OBJECT_EPHEMERAL) {
2376			/* Copied object is always non ephemeral */
2377			new->flags &= ~UCL_OBJECT_EPHEMERAL;
2378		}
2379		new->ref = 1;
2380		/* Unlink from others */
2381		new->next = NULL;
2382		new->prev = new;
2383
2384		/* deep copy of values stored */
2385		if (other->trash_stack[UCL_TRASH_KEY] != NULL) {
2386			new->trash_stack[UCL_TRASH_KEY] =
2387					strdup (other->trash_stack[UCL_TRASH_KEY]);
2388			if (other->key == (const char *)other->trash_stack[UCL_TRASH_KEY]) {
2389				new->key = new->trash_stack[UCL_TRASH_KEY];
2390			}
2391		}
2392		if (other->trash_stack[UCL_TRASH_VALUE] != NULL) {
2393			new->trash_stack[UCL_TRASH_VALUE] =
2394					strdup (other->trash_stack[UCL_TRASH_VALUE]);
2395			if (new->type == UCL_STRING) {
2396				new->value.sv = new->trash_stack[UCL_TRASH_VALUE];
2397			}
2398		}
2399
2400		if (other->type == UCL_ARRAY || other->type == UCL_OBJECT) {
2401			/* reset old value */
2402			memset (&new->value, 0, sizeof (new->value));
2403
2404			while ((cur = ucl_iterate_object (other, &it, true)) != NULL) {
2405				if (other->type == UCL_ARRAY) {
2406					ucl_array_append (new, ucl_object_copy_internal (cur, false));
2407				}
2408				else {
2409					ucl_object_t *cp = ucl_object_copy_internal (cur, true);
2410					if (cp != NULL) {
2411						ucl_object_insert_key (new, cp, cp->key, cp->keylen,
2412								false);
2413					}
2414				}
2415			}
2416		}
2417		else if (allow_array && other->next != NULL) {
2418			LL_FOREACH (other->next, cur) {
2419				ucl_object_t *cp = ucl_object_copy_internal (cur, false);
2420				if (cp != NULL) {
2421					DL_APPEND (new, cp);
2422				}
2423			}
2424		}
2425	}
2426
2427	return new;
2428}
2429
2430ucl_object_t *
2431ucl_object_copy (const ucl_object_t *other)
2432{
2433	return ucl_object_copy_internal (other, true);
2434}
2435
2436void
2437ucl_object_unref (ucl_object_t *obj)
2438{
2439	if (obj != NULL) {
2440#ifdef HAVE_ATOMIC_BUILTINS
2441		unsigned int rc = __sync_sub_and_fetch (&obj->ref, 1);
2442		if (rc == 0) {
2443#else
2444		if (--obj->ref == 0) {
2445#endif
2446			ucl_object_free_internal (obj, true, ucl_object_dtor_unref);
2447		}
2448	}
2449}
2450
2451int
2452ucl_object_compare (const ucl_object_t *o1, const ucl_object_t *o2)
2453{
2454	const ucl_object_t *it1, *it2;
2455	ucl_object_iter_t iter = NULL;
2456	int ret = 0;
2457
2458	if (o1->type != o2->type) {
2459		return (o1->type) - (o2->type);
2460	}
2461
2462	switch (o1->type) {
2463	case UCL_STRING:
2464		if (o1->len == o2->len && o1->len > 0) {
2465			ret = strcmp (ucl_object_tostring(o1), ucl_object_tostring(o2));
2466		}
2467		else {
2468			ret = o1->len - o2->len;
2469		}
2470		break;
2471	case UCL_FLOAT:
2472	case UCL_INT:
2473	case UCL_TIME:
2474		ret = ucl_object_todouble (o1) - ucl_object_todouble (o2);
2475		break;
2476	case UCL_BOOLEAN:
2477		ret = ucl_object_toboolean (o1) - ucl_object_toboolean (o2);
2478		break;
2479	case UCL_ARRAY:
2480		if (o1->len == o2->len && o1->len > 0) {
2481			UCL_ARRAY_GET (vec1, o1);
2482			UCL_ARRAY_GET (vec2, o2);
2483			unsigned i;
2484
2485			/* Compare all elements in both arrays */
2486			for (i = 0; i < vec1->n; i ++) {
2487				it1 = kv_A (*vec1, i);
2488				it2 = kv_A (*vec2, i);
2489
2490				if (it1 == NULL && it2 != NULL) {
2491					return -1;
2492				}
2493				else if (it2 == NULL && it1 != NULL) {
2494					return 1;
2495				}
2496				else if (it1 != NULL && it2 != NULL) {
2497					ret = ucl_object_compare (it1, it2);
2498					if (ret != 0) {
2499						break;
2500					}
2501				}
2502			}
2503		}
2504		else {
2505			ret = o1->len - o2->len;
2506		}
2507		break;
2508	case UCL_OBJECT:
2509		if (o1->len == o2->len && o1->len > 0) {
2510			while ((it1 = ucl_iterate_object (o1, &iter, true)) != NULL) {
2511				it2 = ucl_object_find_key (o2, ucl_object_key (it1));
2512				if (it2 == NULL) {
2513					ret = 1;
2514					break;
2515				}
2516				ret = ucl_object_compare (it1, it2);
2517				if (ret != 0) {
2518					break;
2519				}
2520			}
2521		}
2522		else {
2523			ret = o1->len - o2->len;
2524		}
2525		break;
2526	default:
2527		ret = 0;
2528		break;
2529	}
2530
2531	return ret;
2532}
2533
2534void
2535ucl_object_array_sort (ucl_object_t *ar,
2536		int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2))
2537{
2538	UCL_ARRAY_GET (vec, ar);
2539
2540	if (cmp == NULL || ar == NULL || ar->type != UCL_ARRAY) {
2541		return;
2542	}
2543
2544	qsort (vec->a, vec->n, sizeof (ucl_object_t *),
2545			(int (*)(const void *, const void *))cmp);
2546}
2547
2548#define PRIOBITS 4
2549
2550unsigned int
2551ucl_object_get_priority (const ucl_object_t *obj)
2552{
2553	if (obj == NULL) {
2554		return 0;
2555	}
2556
2557	return (obj->flags >> ((sizeof (obj->flags) * NBBY) - PRIOBITS));
2558}
2559
2560void
2561ucl_object_set_priority (ucl_object_t *obj,
2562		unsigned int priority)
2563{
2564	if (obj != NULL) {
2565		priority &= (0x1 << PRIOBITS) - 1;
2566		obj->flags |= priority << ((sizeof (obj->flags) * NBBY) - PRIOBITS);
2567	}
2568}
2569