1262395Sbapt/* Copyright (c) 2013, Vsevolod Stakhov
2262395Sbapt * All rights reserved.
3262395Sbapt *
4262395Sbapt * Redistribution and use in source and binary forms, with or without
5262395Sbapt * modification, are permitted provided that the following conditions are met:
6262395Sbapt *       * Redistributions of source code must retain the above copyright
7262395Sbapt *         notice, this list of conditions and the following disclaimer.
8262395Sbapt *       * Redistributions in binary form must reproduce the above copyright
9262395Sbapt *         notice, this list of conditions and the following disclaimer in the
10262395Sbapt *         documentation and/or other materials provided with the distribution.
11262395Sbapt *
12262395Sbapt * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13262395Sbapt * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14262395Sbapt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15262395Sbapt * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16262395Sbapt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17262395Sbapt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18262395Sbapt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19262395Sbapt * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20262395Sbapt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21262395Sbapt * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22262395Sbapt */
23262395Sbapt
24262395Sbapt#ifndef UCL_H_
25262395Sbapt#define UCL_H_
26262395Sbapt
27262395Sbapt#include <string.h>
28262395Sbapt#include <stddef.h>
29262395Sbapt#include <stdlib.h>
30262395Sbapt#include <stdint.h>
31262395Sbapt#include <stdbool.h>
32262395Sbapt#include <stdarg.h>
33262395Sbapt#include <stdio.h>
34262395Sbapt
35263032Sbapt#ifdef _WIN32
36263032Sbapt# define UCL_EXTERN __declspec(dllexport)
37263032Sbapt#else
38263032Sbapt# define UCL_EXTERN
39263032Sbapt#endif
40263032Sbapt
41262395Sbapt/**
42262395Sbapt * @mainpage
43262395Sbapt * This is a reference manual for UCL API. You may find the description of UCL format by following this
44262395Sbapt * [github repository](https://github.com/vstakhov/libucl).
45262395Sbapt *
46262395Sbapt * This manual has several main sections:
47262395Sbapt *  - @ref structures
48262395Sbapt *  - @ref utils
49262395Sbapt *  - @ref parser
50262395Sbapt *  - @ref emitter
51262395Sbapt */
52262395Sbapt
53262395Sbapt/**
54262395Sbapt * @file ucl.h
55262395Sbapt * @brief UCL parsing and emitting functions
56262395Sbapt *
57262395Sbapt * UCL is universal configuration language, which is a form of
58262395Sbapt * JSON with less strict rules that make it more comfortable for
59262395Sbapt * using as a configuration language
60262395Sbapt */
61262395Sbapt#ifdef  __cplusplus
62262395Sbaptextern "C" {
63262395Sbapt#endif
64262395Sbapt/*
65262395Sbapt * Memory allocation utilities
66262395Sbapt * UCL_ALLOC(size) - allocate memory for UCL
67262395Sbapt * UCL_FREE(size, ptr) - free memory of specified size at ptr
68262395Sbapt * Default: malloc and free
69262395Sbapt */
70262395Sbapt#ifndef UCL_ALLOC
71262395Sbapt#define UCL_ALLOC(size) malloc(size)
72262395Sbapt#endif
73262395Sbapt#ifndef UCL_FREE
74262395Sbapt#define UCL_FREE(size, ptr) free(ptr)
75262395Sbapt#endif
76262395Sbapt
77262395Sbapt#if    __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
78262395Sbapt#define UCL_WARN_UNUSED_RESULT               \
79262395Sbapt  __attribute__((warn_unused_result))
80262395Sbapt#else
81262395Sbapt#define UCL_WARN_UNUSED_RESULT
82262395Sbapt#endif
83262395Sbapt
84262395Sbapt/**
85262395Sbapt * @defgroup structures Structures and types
86262395Sbapt * UCL defines several enumeration types used for error reporting or specifying flags and attributes.
87262395Sbapt *
88262395Sbapt * @{
89262395Sbapt */
90262395Sbapt
91262395Sbapt/**
92262395Sbapt * The common error codes returned by ucl parser
93262395Sbapt */
94262395Sbapttypedef enum ucl_error {
95262395Sbapt	UCL_EOK = 0, /**< No error */
96262395Sbapt	UCL_ESYNTAX, /**< Syntax error occurred during parsing */
97262395Sbapt	UCL_EIO, /**< IO error occurred during parsing */
98262395Sbapt	UCL_ESTATE, /**< Invalid state machine state */
99262395Sbapt	UCL_ENESTED, /**< Input has too many recursion levels */
100262395Sbapt	UCL_EMACRO, /**< Error processing a macro */
101262395Sbapt	UCL_EINTERNAL, /**< Internal unclassified error */
102262395Sbapt	UCL_ESSL /**< SSL error */
103262395Sbapt} ucl_error_t;
104262395Sbapt
105262395Sbapt/**
106262395Sbapt * #ucl_object_t may have one of specified types, some types are compatible with each other and some are not.
107262395Sbapt * For example, you can always convert #UCL_TIME to #UCL_FLOAT. Also you can convert #UCL_FLOAT to #UCL_INTEGER
108262395Sbapt * by loosing floating point. Every object may be converted to a string by #ucl_object_tostring_forced() function.
109262395Sbapt *
110262395Sbapt */
111262395Sbapttypedef enum ucl_type {
112262395Sbapt	UCL_OBJECT = 0, /**< UCL object - key/value pairs */
113262395Sbapt	UCL_ARRAY, /**< UCL array */
114262395Sbapt	UCL_INT, /**< Integer number */
115262395Sbapt	UCL_FLOAT, /**< Floating point number */
116262395Sbapt	UCL_STRING, /**< Null terminated string */
117262395Sbapt	UCL_BOOLEAN, /**< Boolean value */
118262395Sbapt	UCL_TIME, /**< Time value (floating point number of seconds) */
119262395Sbapt	UCL_USERDATA, /**< Opaque userdata pointer (may be used in macros) */
120262395Sbapt	UCL_NULL /**< Null value */
121262395Sbapt} ucl_type_t;
122262395Sbapt
123262395Sbapt/**
124262395Sbapt * You can use one of these types to serialise #ucl_object_t by using ucl_object_emit().
125262395Sbapt */
126262395Sbapttypedef enum ucl_emitter {
127262395Sbapt	UCL_EMIT_JSON = 0, /**< Emit fine formatted JSON */
128262395Sbapt	UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */
129262395Sbapt	UCL_EMIT_CONFIG, /**< Emit human readable config format */
130262395Sbapt	UCL_EMIT_YAML /**< Emit embedded YAML format */
131262395Sbapt} ucl_emitter_t;
132262395Sbapt
133262395Sbapt/**
134262395Sbapt * These flags defines parser behaviour. If you specify #UCL_PARSER_ZEROCOPY you must ensure
135262395Sbapt * that the input memory is not freed if an object is in use. Moreover, if you want to use
136262395Sbapt * zero-terminated keys and string values then you should not use zero-copy mode, as in this case
137262395Sbapt * UCL still has to perform copying implicitly.
138262395Sbapt */
139262395Sbapttypedef enum ucl_parser_flags {
140262395Sbapt	UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */
141262395Sbapt	UCL_PARSER_ZEROCOPY = 0x2 /**< Parse input in zero-copy mode if possible */
142262395Sbapt} ucl_parser_flags_t;
143262395Sbapt
144262395Sbapt/**
145262395Sbapt * String conversion flags, that are used in #ucl_object_fromstring_common function.
146262395Sbapt */
147262395Sbapttypedef enum ucl_string_flags {
148262395Sbapt	UCL_STRING_ESCAPE = 0x1,  /**< Perform JSON escape */
149262395Sbapt	UCL_STRING_TRIM = 0x2,    /**< Trim leading and trailing whitespaces */
150262395Sbapt	UCL_STRING_PARSE_BOOLEAN = 0x4,    /**< Parse passed string and detect boolean */
151262395Sbapt	UCL_STRING_PARSE_INT = 0x8,    /**< Parse passed string and detect integer number */
152262395Sbapt	UCL_STRING_PARSE_DOUBLE = 0x10,    /**< Parse passed string and detect integer or float number */
153262395Sbapt	UCL_STRING_PARSE_NUMBER =  UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE ,  /**<
154262395Sbapt									Parse passed string and detect number */
155262395Sbapt	UCL_STRING_PARSE =  UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER,   /**<
156262395Sbapt									Parse passed string (and detect booleans and numbers) */
157262395Sbapt	UCL_STRING_PARSE_BYTES = 0x20  /**< Treat numbers as bytes */
158262395Sbapt} ucl_string_flags_t;
159262395Sbapt
160262395Sbapt/**
161262395Sbapt * Basic flags for an object
162262395Sbapt */
163262395Sbapttypedef enum ucl_object_flags {
164262395Sbapt	UCL_OBJECT_ALLOCATED_KEY = 1, /**< An object has key allocated internally */
165262395Sbapt	UCL_OBJECT_ALLOCATED_VALUE = 2, /**< An object has a string value allocated internally */
166262395Sbapt	UCL_OBJECT_NEED_KEY_ESCAPE = 4 /**< The key of an object need to be escaped on output */
167262395Sbapt} ucl_object_flags_t;
168262395Sbapt
169262395Sbapt/**
170262395Sbapt * UCL object structure. Please mention that the most of fields should not be touched by
171262395Sbapt * UCL users. In future, this structure may be converted to private one.
172262395Sbapt */
173262395Sbapttypedef struct ucl_object_s {
174262395Sbapt	/**
175262395Sbapt	 * Variant value type
176262395Sbapt	 */
177262395Sbapt	union {
178262395Sbapt		int64_t iv;							/**< Int value of an object */
179262395Sbapt		const char *sv;					/**< String value of an object */
180262395Sbapt		double dv;							/**< Double value of an object */
181262395Sbapt		struct ucl_object_s *av;			/**< Array					*/
182262395Sbapt		void *ov;							/**< Object					*/
183262395Sbapt		void* ud;							/**< Opaque user data		*/
184262395Sbapt	} value;
185262395Sbapt	const char *key;						/**< Key of an object		*/
186262395Sbapt	struct ucl_object_s *next;				/**< Array handle			*/
187262395Sbapt	struct ucl_object_s *prev;				/**< Array handle			*/
188262395Sbapt	unsigned char* trash_stack[2];			/**< Pointer to allocated chunks */
189262395Sbapt	unsigned keylen;						/**< Lenght of a key		*/
190262395Sbapt	unsigned len;							/**< Size of an object		*/
191262395Sbapt	enum ucl_type type;						/**< Real type				*/
192262395Sbapt	uint16_t ref;							/**< Reference count		*/
193262395Sbapt	uint16_t flags;							/**< Object flags			*/
194262395Sbapt} ucl_object_t;
195262395Sbapt
196262395Sbapt/** @} */
197262395Sbapt
198262395Sbapt/**
199262395Sbapt * @defgroup utils Utility functions
200262395Sbapt * A number of utility functions simplify handling of UCL objects
201262395Sbapt *
202262395Sbapt * @{
203262395Sbapt */
204262395Sbapt/**
205262395Sbapt * Copy and return a key of an object, returned key is zero-terminated
206262395Sbapt * @param obj CL object
207262395Sbapt * @return zero terminated key
208262395Sbapt */
209263032SbaptUCL_EXTERN char* ucl_copy_key_trash (ucl_object_t *obj);
210262395Sbapt
211262395Sbapt/**
212262395Sbapt * Copy and return a string value of an object, returned key is zero-terminated
213262395Sbapt * @param obj CL object
214262395Sbapt * @return zero terminated string representation of object value
215262395Sbapt */
216263032SbaptUCL_EXTERN char* ucl_copy_value_trash (ucl_object_t *obj);
217262395Sbapt
218262395Sbapt/**
219262395Sbapt * Creates a new object
220262395Sbapt * @return new object
221262395Sbapt */
222262395Sbaptstatic inline ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT;
223262395Sbaptstatic inline ucl_object_t *
224262395Sbaptucl_object_new (void)
225262395Sbapt{
226262395Sbapt	ucl_object_t *new;
227262395Sbapt	new = malloc (sizeof (ucl_object_t));
228262395Sbapt	if (new != NULL) {
229262395Sbapt		memset (new, 0, sizeof (ucl_object_t));
230262395Sbapt		new->ref = 1;
231262395Sbapt		new->type = UCL_NULL;
232262395Sbapt	}
233262395Sbapt	return new;
234262395Sbapt}
235262395Sbapt
236262395Sbapt/**
237262395Sbapt * Create new object with type specified
238262395Sbapt * @param type type of a new object
239262395Sbapt * @return new object
240262395Sbapt */
241262395Sbaptstatic inline ucl_object_t* ucl_object_typed_new (unsigned int type) UCL_WARN_UNUSED_RESULT;
242262395Sbaptstatic inline ucl_object_t *
243262395Sbaptucl_object_typed_new (unsigned int type)
244262395Sbapt{
245262395Sbapt	ucl_object_t *new;
246262395Sbapt	new = malloc (sizeof (ucl_object_t));
247262395Sbapt	if (new != NULL) {
248262395Sbapt		memset (new, 0, sizeof (ucl_object_t));
249262395Sbapt		new->ref = 1;
250262395Sbapt		new->type = (type <= UCL_NULL ? type : UCL_NULL);
251262395Sbapt	}
252262395Sbapt	return new;
253262395Sbapt}
254262395Sbapt
255262395Sbapt/**
256262395Sbapt * Convert any string to an ucl object making the specified transformations
257262395Sbapt * @param str fixed size or NULL terminated string
258262395Sbapt * @param len length (if len is zero, than str is treated as NULL terminated)
259262395Sbapt * @param flags conversion flags
260262395Sbapt * @return new object
261262395Sbapt */
262263032SbaptUCL_EXTERN ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len,
263262395Sbapt		enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT;
264262395Sbapt
265262395Sbapt/**
266262395Sbapt * Create a UCL object from the specified string
267262395Sbapt * @param str NULL terminated string, will be json escaped
268262395Sbapt * @return new object
269262395Sbapt */
270262395Sbaptstatic inline ucl_object_t *
271262395Sbaptucl_object_fromstring (const char *str)
272262395Sbapt{
273262395Sbapt	return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE);
274262395Sbapt}
275262395Sbapt
276262395Sbapt/**
277262395Sbapt * Create a UCL object from the specified string
278262395Sbapt * @param str fixed size string, will be json escaped
279262395Sbapt * @param len length of a string
280262395Sbapt * @return new object
281262395Sbapt */
282262395Sbaptstatic inline ucl_object_t *
283262395Sbaptucl_object_fromlstring (const char *str, size_t len)
284262395Sbapt{
285262395Sbapt	return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE);
286262395Sbapt}
287262395Sbapt
288262395Sbapt/**
289262395Sbapt * Create an object from an integer number
290262395Sbapt * @param iv number
291262395Sbapt * @return new object
292262395Sbapt */
293262395Sbaptstatic inline ucl_object_t *
294262395Sbaptucl_object_fromint (int64_t iv)
295262395Sbapt{
296262395Sbapt	ucl_object_t *obj;
297262395Sbapt
298262395Sbapt	obj = ucl_object_new ();
299262395Sbapt	if (obj != NULL) {
300262395Sbapt		obj->type = UCL_INT;
301262395Sbapt		obj->value.iv = iv;
302262395Sbapt	}
303262395Sbapt
304262395Sbapt	return obj;
305262395Sbapt}
306262395Sbapt
307262395Sbapt/**
308262395Sbapt * Create an object from a float number
309262395Sbapt * @param dv number
310262395Sbapt * @return new object
311262395Sbapt */
312262395Sbaptstatic inline ucl_object_t *
313262395Sbaptucl_object_fromdouble (double dv)
314262395Sbapt{
315262395Sbapt	ucl_object_t *obj;
316262395Sbapt
317262395Sbapt	obj = ucl_object_new ();
318262395Sbapt	if (obj != NULL) {
319262395Sbapt		obj->type = UCL_FLOAT;
320262395Sbapt		obj->value.dv = dv;
321262395Sbapt	}
322262395Sbapt
323262395Sbapt	return obj;
324262395Sbapt}
325262395Sbapt
326262395Sbapt/**
327262395Sbapt * Create an object from a boolean
328262395Sbapt * @param bv bool value
329262395Sbapt * @return new object
330262395Sbapt */
331262395Sbaptstatic inline ucl_object_t *
332262395Sbaptucl_object_frombool (bool bv)
333262395Sbapt{
334262395Sbapt	ucl_object_t *obj;
335262395Sbapt
336262395Sbapt	obj = ucl_object_new ();
337262395Sbapt	if (obj != NULL) {
338262395Sbapt		obj->type = UCL_BOOLEAN;
339262395Sbapt		obj->value.iv = bv;
340262395Sbapt	}
341262395Sbapt
342262395Sbapt	return obj;
343262395Sbapt}
344262395Sbapt
345262395Sbapt/**
346262395Sbapt * Insert a object 'elt' to the hash 'top' and associate it with key 'key'
347262395Sbapt * @param top destination object (will be created automatically if top is NULL)
348262395Sbapt * @param elt element to insert (must NOT be NULL)
349262395Sbapt * @param key key to associate with this object (either const or preallocated)
350262395Sbapt * @param keylen length of the key (or 0 for NULL terminated keys)
351262395Sbapt * @param copy_key make an internal copy of key
352262395Sbapt * @return new value of top object
353262395Sbapt */
354263032SbaptUCL_EXTERN ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt,
355262395Sbapt		const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT;
356262395Sbapt
357262395Sbapt/**
358262395Sbapt * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed,
359262395Sbapt * if no object has been found this function works like ucl_object_insert_key()
360262395Sbapt * @param top destination object (will be created automatically if top is NULL)
361262395Sbapt * @param elt element to insert (must NOT be NULL)
362262395Sbapt * @param key key to associate with this object (either const or preallocated)
363262395Sbapt * @param keylen length of the key (or 0 for NULL terminated keys)
364262395Sbapt * @param copy_key make an internal copy of key
365262395Sbapt * @return new value of top object
366262395Sbapt */
367263032SbaptUCL_EXTERN ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt,
368262395Sbapt		const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT;
369262395Sbapt
370262395Sbapt/**
371263032Sbapt * Delete a object associated with key 'key', old object will be unrefered,
372263032Sbapt * @param top object
373263032Sbapt * @param key key associated to the object to remove
374263032Sbapt * @param keylen length of the key (or 0 for NULL terminated keys)
375263032Sbapt */
376263032SbaptUCL_EXTERN bool ucl_object_delete_keyl (ucl_object_t *top, const char *key, size_t keylen);
377263032Sbapt
378263032Sbapt/**
379263032Sbapt * Delete a object associated with key 'key', old object will be unrefered,
380263032Sbapt * @param top object
381263032Sbapt * @param key key associated to the object to remove
382263032Sbapt */
383263032SbaptUCL_EXTERN bool ucl_object_delete_key (ucl_object_t *top, const char *key);
384263032Sbapt
385263032Sbapt/**
386262395Sbapt * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist,
387262395Sbapt * try to merge its content
388262395Sbapt * @param top destination object (will be created automatically if top is NULL)
389262395Sbapt * @param elt element to insert (must NOT be NULL)
390262395Sbapt * @param key key to associate with this object (either const or preallocated)
391262395Sbapt * @param keylen length of the key (or 0 for NULL terminated keys)
392262395Sbapt * @param copy_key make an internal copy of key
393262395Sbapt * @return new value of top object
394262395Sbapt */
395263032SbaptUCL_EXTERN ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt,
396262395Sbapt		const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT;
397262395Sbapt
398262395Sbapt/**
399262395Sbapt * Append an element to the front of array object
400262395Sbapt * @param top destination object (will be created automatically if top is NULL)
401262395Sbapt * @param elt element to append (must NOT be NULL)
402262395Sbapt * @return new value of top object
403262395Sbapt */
404262395Sbaptstatic inline ucl_object_t * ucl_array_append (ucl_object_t *top,
405262395Sbapt		ucl_object_t *elt) UCL_WARN_UNUSED_RESULT;
406262395Sbaptstatic inline ucl_object_t *
407262395Sbaptucl_array_append (ucl_object_t *top, ucl_object_t *elt)
408262395Sbapt{
409262395Sbapt	ucl_object_t *head;
410262395Sbapt
411262395Sbapt	if (elt == NULL) {
412262395Sbapt		return NULL;
413262395Sbapt	}
414262395Sbapt
415262395Sbapt	if (top == NULL) {
416262395Sbapt		top = ucl_object_typed_new (UCL_ARRAY);
417262395Sbapt		top->value.av = elt;
418262395Sbapt		elt->next = NULL;
419262395Sbapt		elt->prev = elt;
420262395Sbapt		top->len = 1;
421262395Sbapt	}
422262395Sbapt	else {
423262395Sbapt		head = top->value.av;
424262395Sbapt		if (head == NULL) {
425262395Sbapt			top->value.av = elt;
426262395Sbapt			elt->prev = elt;
427262395Sbapt		}
428262395Sbapt		else {
429262395Sbapt			elt->prev = head->prev;
430262395Sbapt			head->prev->next = elt;
431262395Sbapt			head->prev = elt;
432262395Sbapt		}
433262395Sbapt		elt->next = NULL;
434262395Sbapt		top->len ++;
435262395Sbapt	}
436262395Sbapt
437262395Sbapt	return top;
438262395Sbapt}
439262395Sbapt
440262395Sbapt/**
441262395Sbapt * Append an element to the start of array object
442262395Sbapt * @param top destination object (will be created automatically if top is NULL)
443262395Sbapt * @param elt element to append (must NOT be NULL)
444262395Sbapt * @return new value of top object
445262395Sbapt */
446262395Sbaptstatic inline ucl_object_t * ucl_array_prepend (ucl_object_t *top,
447262395Sbapt		ucl_object_t *elt) UCL_WARN_UNUSED_RESULT;
448262395Sbaptstatic inline ucl_object_t *
449262395Sbaptucl_array_prepend (ucl_object_t *top, ucl_object_t *elt)
450262395Sbapt{
451262395Sbapt	ucl_object_t *head;
452262395Sbapt
453262395Sbapt	if (elt == NULL) {
454262395Sbapt		return NULL;
455262395Sbapt	}
456262395Sbapt
457262395Sbapt	if (top == NULL) {
458262395Sbapt		top = ucl_object_typed_new (UCL_ARRAY);
459262395Sbapt		top->value.av = elt;
460262395Sbapt		elt->next = NULL;
461262395Sbapt		elt->prev = elt;
462262395Sbapt		top->len = 1;
463262395Sbapt	}
464262395Sbapt	else {
465262395Sbapt		head = top->value.av;
466262395Sbapt		if (head == NULL) {
467262395Sbapt			top->value.av = elt;
468262395Sbapt			elt->prev = elt;
469262395Sbapt		}
470262395Sbapt		else {
471262395Sbapt			elt->prev = head->prev;
472262395Sbapt			head->prev = elt;
473262395Sbapt		}
474262395Sbapt		elt->next = head;
475262395Sbapt		top->value.av = elt;
476262395Sbapt		top->len ++;
477262395Sbapt	}
478262395Sbapt
479262395Sbapt	return top;
480262395Sbapt}
481262395Sbapt
482262395Sbapt/**
483262395Sbapt * Removes an element `elt` from the array `top`. Caller must unref the returned object when it is not
484262395Sbapt * needed.
485262395Sbapt * @param top array ucl object
486262395Sbapt * @param elt element to remove
487262395Sbapt * @return removed element or NULL if `top` is NULL or not an array
488262395Sbapt */
489262395Sbaptstatic inline ucl_object_t *
490262395Sbaptucl_array_delete (ucl_object_t *top, ucl_object_t *elt)
491262395Sbapt{
492262395Sbapt	ucl_object_t *head;
493262395Sbapt
494262395Sbapt	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
495262395Sbapt		return NULL;
496262395Sbapt	}
497262395Sbapt	head = top->value.av;
498262395Sbapt
499262395Sbapt	if (elt->prev == elt) {
500262395Sbapt		top->value.av = NULL;
501262395Sbapt	}
502262395Sbapt	else if (elt == head) {
503262395Sbapt		elt->next->prev = elt->prev;
504262395Sbapt		top->value.av = elt->next;
505262395Sbapt	}
506262395Sbapt	else {
507262395Sbapt		elt->prev->next = elt->next;
508262395Sbapt		if (elt->next) {
509262395Sbapt			elt->next->prev = elt->prev;
510262395Sbapt		}
511262395Sbapt		else {
512262395Sbapt			head->prev = elt->prev;
513262395Sbapt		}
514262395Sbapt	}
515262395Sbapt	elt->next = NULL;
516262395Sbapt	elt->prev = elt;
517262395Sbapt	top->len --;
518262395Sbapt
519262395Sbapt	return elt;
520262395Sbapt}
521262395Sbapt
522262395Sbapt/**
523262395Sbapt * Returns the first element of the array `top`
524262395Sbapt * @param top array ucl object
525262395Sbapt * @return element or NULL if `top` is NULL or not an array
526262395Sbapt */
527262395Sbaptstatic inline ucl_object_t *
528262395Sbaptucl_array_head (ucl_object_t *top)
529262395Sbapt{
530262395Sbapt	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
531262395Sbapt		return NULL;
532262395Sbapt	}
533262395Sbapt	return top->value.av;
534262395Sbapt}
535262395Sbapt
536262395Sbapt/**
537262395Sbapt * Returns the last element of the array `top`
538262395Sbapt * @param top array ucl object
539262395Sbapt * @return element or NULL if `top` is NULL or not an array
540262395Sbapt */
541262395Sbaptstatic inline ucl_object_t *
542262395Sbaptucl_array_tail (ucl_object_t *top)
543262395Sbapt{
544262395Sbapt	if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) {
545262395Sbapt		return NULL;
546262395Sbapt	}
547262395Sbapt	return top->value.av->prev;
548262395Sbapt}
549262395Sbapt
550262395Sbapt/**
551262395Sbapt * Removes the last element from the array `top`. Caller must unref the returned object when it is not
552262395Sbapt * needed.
553262395Sbapt * @param top array ucl object
554262395Sbapt * @return removed element or NULL if `top` is NULL or not an array
555262395Sbapt */
556262395Sbaptstatic inline ucl_object_t *
557262395Sbaptucl_array_pop_last (ucl_object_t *top)
558262395Sbapt{
559262395Sbapt	return ucl_array_delete (top, ucl_array_tail (top));
560262395Sbapt}
561262395Sbapt
562262395Sbapt/**
563262395Sbapt * Removes the first element from the array `top`. Caller must unref the returned object when it is not
564262395Sbapt * needed.
565262395Sbapt * @param top array ucl object
566262395Sbapt * @return removed element or NULL if `top` is NULL or not an array
567262395Sbapt */
568262395Sbaptstatic inline ucl_object_t *
569262395Sbaptucl_array_pop_first (ucl_object_t *top)
570262395Sbapt{
571262395Sbapt	return ucl_array_delete (top, ucl_array_head (top));
572262395Sbapt}
573262395Sbapt
574262395Sbapt/**
575262395Sbapt * Append a element to another element forming an implicit array
576262395Sbapt * @param head head to append (may be NULL)
577262395Sbapt * @param elt new element
578262395Sbapt * @return new head if applicable
579262395Sbapt */
580262395Sbaptstatic inline ucl_object_t * ucl_elt_append (ucl_object_t *head,
581262395Sbapt		ucl_object_t *elt) UCL_WARN_UNUSED_RESULT;
582262395Sbaptstatic inline ucl_object_t *
583262395Sbaptucl_elt_append (ucl_object_t *head, ucl_object_t *elt)
584262395Sbapt{
585262395Sbapt
586262395Sbapt	if (head == NULL) {
587262395Sbapt		elt->next = NULL;
588262395Sbapt		elt->prev = elt;
589262395Sbapt		head = elt;
590262395Sbapt	}
591262395Sbapt	else {
592262395Sbapt		elt->prev = head->prev;
593262395Sbapt		head->prev->next = elt;
594262395Sbapt		head->prev = elt;
595262395Sbapt		elt->next = NULL;
596262395Sbapt	}
597262395Sbapt
598262395Sbapt	return head;
599262395Sbapt}
600262395Sbapt
601262395Sbapt/**
602262395Sbapt * Converts an object to double value
603262395Sbapt * @param obj CL object
604262395Sbapt * @param target target double variable
605262395Sbapt * @return true if conversion was successful
606262395Sbapt */
607262395Sbaptstatic inline bool
608262395Sbaptucl_object_todouble_safe (ucl_object_t *obj, double *target)
609262395Sbapt{
610262395Sbapt	if (obj == NULL) {
611262395Sbapt		return false;
612262395Sbapt	}
613262395Sbapt	switch (obj->type) {
614262395Sbapt	case UCL_INT:
615262395Sbapt		*target = obj->value.iv; /* Probaly could cause overflow */
616262395Sbapt		break;
617262395Sbapt	case UCL_FLOAT:
618262395Sbapt	case UCL_TIME:
619262395Sbapt		*target = obj->value.dv;
620262395Sbapt		break;
621262395Sbapt	default:
622262395Sbapt		return false;
623262395Sbapt	}
624262395Sbapt
625262395Sbapt	return true;
626262395Sbapt}
627262395Sbapt
628262395Sbapt/**
629262395Sbapt * Unsafe version of \ref ucl_obj_todouble_safe
630262395Sbapt * @param obj CL object
631262395Sbapt * @return double value
632262395Sbapt */
633262395Sbaptstatic inline double
634262395Sbaptucl_object_todouble (ucl_object_t *obj)
635262395Sbapt{
636262395Sbapt	double result = 0.;
637262395Sbapt
638262395Sbapt	ucl_object_todouble_safe (obj, &result);
639262395Sbapt	return result;
640262395Sbapt}
641262395Sbapt
642262395Sbapt/**
643262395Sbapt * Converts an object to integer value
644262395Sbapt * @param obj CL object
645262395Sbapt * @param target target integer variable
646262395Sbapt * @return true if conversion was successful
647262395Sbapt */
648262395Sbaptstatic inline bool
649262395Sbaptucl_object_toint_safe (ucl_object_t *obj, int64_t *target)
650262395Sbapt{
651262395Sbapt	if (obj == NULL) {
652262395Sbapt		return false;
653262395Sbapt	}
654262395Sbapt	switch (obj->type) {
655262395Sbapt	case UCL_INT:
656262395Sbapt		*target = obj->value.iv;
657262395Sbapt		break;
658262395Sbapt	case UCL_FLOAT:
659262395Sbapt	case UCL_TIME:
660262395Sbapt		*target = obj->value.dv; /* Loosing of decimal points */
661262395Sbapt		break;
662262395Sbapt	default:
663262395Sbapt		return false;
664262395Sbapt	}
665262395Sbapt
666262395Sbapt	return true;
667262395Sbapt}
668262395Sbapt
669262395Sbapt/**
670262395Sbapt * Unsafe version of \ref ucl_obj_toint_safe
671262395Sbapt * @param obj CL object
672262395Sbapt * @return int value
673262395Sbapt */
674262395Sbaptstatic inline int64_t
675262395Sbaptucl_object_toint (ucl_object_t *obj)
676262395Sbapt{
677262395Sbapt	int64_t result = 0;
678262395Sbapt
679262395Sbapt	ucl_object_toint_safe (obj, &result);
680262395Sbapt	return result;
681262395Sbapt}
682262395Sbapt
683262395Sbapt/**
684262395Sbapt * Converts an object to boolean value
685262395Sbapt * @param obj CL object
686262395Sbapt * @param target target boolean variable
687262395Sbapt * @return true if conversion was successful
688262395Sbapt */
689262395Sbaptstatic inline bool
690262395Sbaptucl_object_toboolean_safe (ucl_object_t *obj, bool *target)
691262395Sbapt{
692262395Sbapt	if (obj == NULL) {
693262395Sbapt		return false;
694262395Sbapt	}
695262395Sbapt	switch (obj->type) {
696262395Sbapt	case UCL_BOOLEAN:
697262395Sbapt		*target = (obj->value.iv == true);
698262395Sbapt		break;
699262395Sbapt	default:
700262395Sbapt		return false;
701262395Sbapt	}
702262395Sbapt
703262395Sbapt	return true;
704262395Sbapt}
705262395Sbapt
706262395Sbapt/**
707262395Sbapt * Unsafe version of \ref ucl_obj_toboolean_safe
708262395Sbapt * @param obj CL object
709262395Sbapt * @return boolean value
710262395Sbapt */
711262395Sbaptstatic inline bool
712262395Sbaptucl_object_toboolean (ucl_object_t *obj)
713262395Sbapt{
714262395Sbapt	bool result = false;
715262395Sbapt
716262395Sbapt	ucl_object_toboolean_safe (obj, &result);
717262395Sbapt	return result;
718262395Sbapt}
719262395Sbapt
720262395Sbapt/**
721262395Sbapt * Converts an object to string value
722262395Sbapt * @param obj CL object
723262395Sbapt * @param target target string variable, no need to free value
724262395Sbapt * @return true if conversion was successful
725262395Sbapt */
726262395Sbaptstatic inline bool
727262395Sbaptucl_object_tostring_safe (ucl_object_t *obj, const char **target)
728262395Sbapt{
729262395Sbapt	if (obj == NULL) {
730262395Sbapt		return false;
731262395Sbapt	}
732262395Sbapt
733262395Sbapt	switch (obj->type) {
734262395Sbapt	case UCL_STRING:
735262395Sbapt		*target = ucl_copy_value_trash (obj);
736262395Sbapt		break;
737262395Sbapt	default:
738262395Sbapt		return false;
739262395Sbapt	}
740262395Sbapt
741262395Sbapt	return true;
742262395Sbapt}
743262395Sbapt
744262395Sbapt/**
745262395Sbapt * Unsafe version of \ref ucl_obj_tostring_safe
746262395Sbapt * @param obj CL object
747262395Sbapt * @return string value
748262395Sbapt */
749262395Sbaptstatic inline const char *
750262395Sbaptucl_object_tostring (ucl_object_t *obj)
751262395Sbapt{
752262395Sbapt	const char *result = NULL;
753262395Sbapt
754262395Sbapt	ucl_object_tostring_safe (obj, &result);
755262395Sbapt	return result;
756262395Sbapt}
757262395Sbapt
758262395Sbapt/**
759262395Sbapt * Convert any object to a string in JSON notation if needed
760262395Sbapt * @param obj CL object
761262395Sbapt * @return string value
762262395Sbapt */
763262395Sbaptstatic inline const char *
764262395Sbaptucl_object_tostring_forced (ucl_object_t *obj)
765262395Sbapt{
766262395Sbapt	return ucl_copy_value_trash (obj);
767262395Sbapt}
768262395Sbapt
769262395Sbapt/**
770262395Sbapt * Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it
771262395Sbapt * allows zero-copy (if #UCL_PARSER_ZEROCOPY has been used during parsing)
772262395Sbapt * @param obj CL object
773262395Sbapt * @param target target string variable, no need to free value
774262395Sbapt * @param tlen target length
775262395Sbapt * @return true if conversion was successful
776262395Sbapt */
777262395Sbaptstatic inline bool
778262395Sbaptucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen)
779262395Sbapt{
780262395Sbapt	if (obj == NULL) {
781262395Sbapt		return false;
782262395Sbapt	}
783262395Sbapt	switch (obj->type) {
784262395Sbapt	case UCL_STRING:
785262395Sbapt		*target = obj->value.sv;
786262395Sbapt		*tlen = obj->len;
787262395Sbapt		break;
788262395Sbapt	default:
789262395Sbapt		return false;
790262395Sbapt	}
791262395Sbapt
792262395Sbapt	return true;
793262395Sbapt}
794262395Sbapt
795262395Sbapt/**
796262395Sbapt * Unsafe version of \ref ucl_obj_tolstring_safe
797262395Sbapt * @param obj CL object
798262395Sbapt * @return string value
799262395Sbapt */
800262395Sbaptstatic inline const char *
801262395Sbaptucl_object_tolstring (ucl_object_t *obj, size_t *tlen)
802262395Sbapt{
803262395Sbapt	const char *result = NULL;
804262395Sbapt
805262395Sbapt	ucl_object_tolstring_safe (obj, &result, tlen);
806262395Sbapt	return result;
807262395Sbapt}
808262395Sbapt
809262395Sbapt/**
810262395Sbapt * Return object identified by a key in the specified object
811262395Sbapt * @param obj object to get a key from (must be of type UCL_OBJECT)
812262395Sbapt * @param key key to search
813262395Sbapt * @return object matched the specified key or NULL if key is not found
814262395Sbapt */
815263032SbaptUCL_EXTERN ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key);
816262395Sbapt
817262395Sbapt/**
818262395Sbapt * Return object identified by a fixed size key in the specified object
819262395Sbapt * @param obj object to get a key from (must be of type UCL_OBJECT)
820262395Sbapt * @param key key to search
821262395Sbapt * @param klen length of a key
822262395Sbapt * @return object matched the specified key or NULL if key is not found
823262395Sbapt */
824263032SbaptUCL_EXTERN ucl_object_t *ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen);
825262395Sbapt
826262395Sbapt/**
827262395Sbapt * Returns a key of an object as a NULL terminated string
828262395Sbapt * @param obj CL object
829262395Sbapt * @return key or NULL if there is no key
830262395Sbapt */
831262395Sbaptstatic inline const char *
832262395Sbaptucl_object_key (ucl_object_t *obj)
833262395Sbapt{
834262395Sbapt	return ucl_copy_key_trash (obj);
835262395Sbapt}
836262395Sbapt
837262395Sbapt/**
838262395Sbapt * Returns a key of an object as a fixed size string (may be more efficient)
839262395Sbapt * @param obj CL object
840262395Sbapt * @param len target key length
841262395Sbapt * @return key pointer
842262395Sbapt */
843262395Sbaptstatic inline const char *
844262395Sbaptucl_object_keyl (ucl_object_t *obj, size_t *len)
845262395Sbapt{
846262395Sbapt	*len = obj->keylen;
847262395Sbapt	return obj->key;
848262395Sbapt}
849262395Sbapt
850262395Sbapt/**
851262395Sbapt * Free ucl object
852262395Sbapt * @param obj ucl object to free
853262395Sbapt */
854263032SbaptUCL_EXTERN void ucl_object_free (ucl_object_t *obj);
855262395Sbapt
856262395Sbapt/**
857262395Sbapt * Increase reference count for an object
858262395Sbapt * @param obj object to ref
859262395Sbapt */
860262395Sbaptstatic inline ucl_object_t *
861262395Sbaptucl_object_ref (ucl_object_t *obj) {
862262395Sbapt	obj->ref ++;
863262395Sbapt	return obj;
864262395Sbapt}
865262395Sbapt
866262395Sbapt/**
867262395Sbapt * Decrease reference count for an object
868262395Sbapt * @param obj object to unref
869262395Sbapt */
870262395Sbaptstatic inline void
871262395Sbaptucl_object_unref (ucl_object_t *obj) {
872262395Sbapt	if (obj != NULL && --obj->ref <= 0) {
873262395Sbapt		ucl_object_free (obj);
874262395Sbapt	}
875262395Sbapt}
876262395Sbapt/**
877262395Sbapt * Opaque iterator object
878262395Sbapt */
879262395Sbapttypedef void* ucl_object_iter_t;
880262395Sbapt
881262395Sbapt/**
882262395Sbapt * Get next key from an object
883262395Sbapt * @param obj object to iterate
884262395Sbapt * @param iter opaque iterator, must be set to NULL on the first call:
885262395Sbapt * ucl_object_iter_t it = NULL;
886262395Sbapt * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ...
887262395Sbapt * @return the next object or NULL
888262395Sbapt */
889263032SbaptUCL_EXTERN ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values);
890262395Sbapt/** @} */
891262395Sbapt
892262395Sbapt
893262395Sbapt/**
894262395Sbapt * @defgroup parser Parsing functions
895262395Sbapt * These functions are used to parse UCL objects
896262395Sbapt *
897262395Sbapt * @{
898262395Sbapt */
899262395Sbapt
900262395Sbapt/**
901262395Sbapt * Macro handler for a parser
902262395Sbapt * @param data the content of macro
903262395Sbapt * @param len the length of content
904262395Sbapt * @param ud opaque user data
905262395Sbapt * @param err error pointer
906262395Sbapt * @return true if macro has been parsed
907262395Sbapt */
908262395Sbapttypedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud);
909262395Sbapt
910262395Sbapt/* Opaque parser */
911262395Sbaptstruct ucl_parser;
912262395Sbapt
913262395Sbapt/**
914262395Sbapt * Creates new parser object
915262395Sbapt * @param pool pool to allocate memory from
916262395Sbapt * @return new parser object
917262395Sbapt */
918263032SbaptUCL_EXTERN struct ucl_parser* ucl_parser_new (int flags);
919262395Sbapt
920262395Sbapt/**
921262395Sbapt * Register new handler for a macro
922262395Sbapt * @param parser parser object
923262395Sbapt * @param macro macro name (without leading dot)
924262395Sbapt * @param handler handler (it is called immediately after macro is parsed)
925262395Sbapt * @param ud opaque user data for a handler
926262395Sbapt */
927263032SbaptUCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
928262395Sbapt		ucl_macro_handler handler, void* ud);
929262395Sbapt
930262395Sbapt/**
931262395Sbapt * Register new parser variable
932262395Sbapt * @param parser parser object
933262395Sbapt * @param var variable name
934262395Sbapt * @param value variable value
935262395Sbapt */
936263032SbaptUCL_EXTERN void ucl_parser_register_variable (struct ucl_parser *parser, const char *var,
937262395Sbapt		const char *value);
938262395Sbapt
939262395Sbapt/**
940262395Sbapt * Load new chunk to a parser
941262395Sbapt * @param parser parser structure
942262395Sbapt * @param data the pointer to the beginning of a chunk
943262395Sbapt * @param len the length of a chunk
944262395Sbapt * @param err if *err is NULL it is set to parser error
945262395Sbapt * @return true if chunk has been added and false in case of error
946262395Sbapt */
947263032SbaptUCL_EXTERN bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len);
948262395Sbapt
949262395Sbapt/**
950262395Sbapt * Load and add data from a file
951262395Sbapt * @param parser parser structure
952262395Sbapt * @param filename the name of file
953262395Sbapt * @param err if *err is NULL it is set to parser error
954262395Sbapt * @return true if chunk has been added and false in case of error
955262395Sbapt */
956263032SbaptUCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename);
957262395Sbapt
958262395Sbapt/**
959262395Sbapt * Get a top object for a parser
960262395Sbapt * @param parser parser structure
961262395Sbapt * @param err if *err is NULL it is set to parser error
962262395Sbapt * @return top parser object or NULL
963262395Sbapt */
964263032SbaptUCL_EXTERN ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser);
965262395Sbapt
966262395Sbapt/**
967262395Sbapt * Get the error string if failing
968262395Sbapt * @param parser parser object
969262395Sbapt */
970263032SbaptUCL_EXTERN const char *ucl_parser_get_error(struct ucl_parser *parser);
971262395Sbapt/**
972262395Sbapt * Free ucl parser object
973262395Sbapt * @param parser parser object
974262395Sbapt */
975263032SbaptUCL_EXTERN void ucl_parser_free (struct ucl_parser *parser);
976262395Sbapt
977262395Sbapt/**
978262395Sbapt * Add new public key to parser for signatures check
979262395Sbapt * @param parser parser object
980262395Sbapt * @param key PEM representation of a key
981262395Sbapt * @param len length of the key
982262395Sbapt * @param err if *err is NULL it is set to parser error
983262395Sbapt * @return true if a key has been successfully added
984262395Sbapt */
985263032SbaptUCL_EXTERN bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len);
986262395Sbapt
987262395Sbapt/**
988262395Sbapt * Set FILENAME and CURDIR variables in parser
989262395Sbapt * @param parser parser object
990262395Sbapt * @param filename filename to set or NULL to set FILENAME to "undef" and CURDIR to getcwd()
991262395Sbapt * @param need_expand perform realpath() if this variable is true and filename is not NULL
992262395Sbapt * @return true if variables has been set
993262395Sbapt */
994263032SbaptUCL_EXTERN bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename,
995262395Sbapt		bool need_expand);
996262395Sbapt
997262395Sbapt/** @} */
998262395Sbapt
999262395Sbapt/**
1000262395Sbapt * @defgroup emitter Emitting functions
1001262395Sbapt * These functions are used to serialise UCL objects to some string representation.
1002262395Sbapt *
1003262395Sbapt * @{
1004262395Sbapt */
1005262395Sbapt
1006262395Sbapt/**
1007262395Sbapt * Structure using for emitter callbacks
1008262395Sbapt */
1009262395Sbaptstruct ucl_emitter_functions {
1010262395Sbapt	/** Append a single character */
1011262395Sbapt	int (*ucl_emitter_append_character) (unsigned char c, size_t nchars, void *ud);
1012262395Sbapt	/** Append a string of a specified length */
1013262395Sbapt	int (*ucl_emitter_append_len) (unsigned const char *str, size_t len, void *ud);
1014262395Sbapt	/** Append a 64 bit integer */
1015262395Sbapt	int (*ucl_emitter_append_int) (int64_t elt, void *ud);
1016262395Sbapt	/** Append floating point element */
1017262395Sbapt	int (*ucl_emitter_append_double) (double elt, void *ud);
1018262395Sbapt	/** Opaque userdata pointer */
1019262395Sbapt	void *ud;
1020262395Sbapt};
1021262395Sbapt
1022262395Sbapt/**
1023262395Sbapt * Emit object to a string
1024262395Sbapt * @param obj object
1025262395Sbapt * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
1026262395Sbapt * #UCL_EMIT_CONFIG then emit config like object
1027262395Sbapt * @return dump of an object (must be freed after using) or NULL in case of error
1028262395Sbapt */
1029263032SbaptUCL_EXTERN unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type);
1030262395Sbapt
1031262395Sbapt/**
1032262395Sbapt * Emit object to a string
1033262395Sbapt * @param obj object
1034262395Sbapt * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
1035262395Sbapt * #UCL_EMIT_CONFIG then emit config like object
1036262395Sbapt * @return dump of an object (must be freed after using) or NULL in case of error
1037262395Sbapt */
1038263032SbaptUCL_EXTERN bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type,
1039262395Sbapt		struct ucl_emitter_functions *emitter);
1040262395Sbapt/** @} */
1041262395Sbapt
1042262395Sbapt#ifdef  __cplusplus
1043262395Sbapt}
1044262395Sbapt#endif
1045262395Sbapt/*
1046262395Sbapt * XXX: Poorly named API functions, need to replace them with the appropriate
1047262395Sbapt * named function. All API functions *must* use naming ucl_object_*. Usage of
1048262395Sbapt * ucl_obj* should be avoided.
1049262395Sbapt */
1050262395Sbapt#define ucl_obj_todouble_safe ucl_object_todouble_safe
1051262395Sbapt#define ucl_obj_todouble ucl_object_todouble
1052262395Sbapt#define ucl_obj_tostring ucl_object_tostring
1053262395Sbapt#define ucl_obj_tostring_safe ucl_object_tostring_safe
1054262395Sbapt#define ucl_obj_tolstring ucl_object_tolstring
1055262395Sbapt#define ucl_obj_tolstring_safe ucl_object_tolstring_safe
1056262395Sbapt#define ucl_obj_toint ucl_object_toint
1057262395Sbapt#define ucl_obj_toint_safe ucl_object_toint_safe
1058262395Sbapt#define ucl_obj_toboolean ucl_object_toboolean
1059262395Sbapt#define ucl_obj_toboolean_safe ucl_object_toboolean_safe
1060262395Sbapt#define ucl_obj_get_key ucl_object_find_key
1061262395Sbapt#define ucl_obj_get_keyl ucl_object_find_keyl
1062262395Sbapt#define ucl_obj_unref ucl_object_unref
1063262395Sbapt#define ucl_obj_ref ucl_object_ref
1064262395Sbapt#define ucl_obj_free ucl_object_free
1065262395Sbapt
1066262395Sbapt#endif /* UCL_H_ */
1067