xref: /freebsd/contrib/libucl/include/ucl.h (revision abda442d92fdbadcf81c79bc9ddba001d133c429)
1 /* Copyright (c) 2013-2015, Vsevolod Stakhov
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *       * Redistributions of source code must retain the above copyright
7  *         notice, this list of conditions and the following disclaimer.
8  *       * Redistributions in binary form must reproduce the above copyright
9  *         notice, this list of conditions and the following disclaimer in the
10  *         documentation and/or other materials provided with the distribution.
11  *
12  * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
13  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
16  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
19  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  */
23 
24 #ifndef UCL_H_
25 #define UCL_H_
26 
27 #include <string.h>
28 #include <stddef.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <stdbool.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 
35 #ifdef _WIN32
36 #define UCL_EXTERN __declspec(dllexport)
37 #else
38 #define UCL_EXTERN
39 #endif
40 
41 /**
42  * @mainpage
43  * This is a reference manual for UCL API. You may find the description of UCL format by following this
44  * [github repository](https://github.com/vstakhov/libucl).
45  *
46  * This manual has several main sections:
47  *  - @ref structures
48  *  - @ref utils
49  *  - @ref parser
50  *  - @ref emitter
51  */
52 
53 /**
54  * @file ucl.h
55  * @brief UCL parsing and emitting functions
56  *
57  * UCL is universal configuration language, which is a form of
58  * JSON with less strict rules that make it more comfortable for
59  * using as a configuration language
60  */
61 #ifdef __cplusplus
62 extern "C" {
63 #endif
64 /*
65  * Memory allocation utilities
66  * UCL_ALLOC(size) - allocate memory for UCL
67  * UCL_FREE(size, ptr) - free memory of specified size at ptr
68  * Default: malloc and free
69  */
70 #ifndef UCL_ALLOC
71 #define UCL_ALLOC(size) malloc(size)
72 #endif
73 #ifndef UCL_FREE
74 #define UCL_FREE(size, ptr) free(ptr)
75 #endif
76 #ifndef UCL_REALLOC
77 #define UCL_REALLOC(ptr, size) realloc(ptr, size)
78 #endif
79 #ifndef UCL_STRDUP
80 static inline char *ucl_strdup_impl(const char *s)
81 {
82 	size_t len = strlen(s) + 1;
83 	char *p = (char *) UCL_ALLOC(len);
84 	if (p) memcpy(p, s, len);
85 	return p;
86 }
87 #define UCL_STRDUP(str) ucl_strdup_impl(str)
88 #endif
89 
90 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
91 #define UCL_WARN_UNUSED_RESULT \
92 	__attribute__((warn_unused_result))
93 #else
94 #define UCL_WARN_UNUSED_RESULT
95 #endif
96 
97 #ifdef __GNUC__
98 #define UCL_DEPRECATED(func) func __attribute__((deprecated))
99 #elif defined(_MSC_VER)
100 #define UCL_DEPRECATED(func) __declspec(deprecated) func
101 #else
102 #define UCL_DEPRECATED(func) func
103 #endif
104 
105 /**
106  * @defgroup structures Structures and types
107  * UCL defines several enumeration types used for error reporting or specifying flags and attributes.
108  *
109  * @{
110  */
111 
112 /**
113  * The common error codes returned by ucl parser
114  */
115 typedef enum ucl_error {
116 	UCL_EOK = 0,   /**< No error */
117 	UCL_ESYNTAX,   /**< Syntax error occurred during parsing */
118 	UCL_EIO,       /**< IO error occurred during parsing */
119 	UCL_ESTATE,    /**< Invalid state machine state */
120 	UCL_ENESTED,   /**< Input has too many recursion levels */
121 	UCL_EUNPAIRED, /**< Input has too many recursion levels */
122 	UCL_EMACRO,    /**< Error processing a macro */
123 	UCL_EINTERNAL, /**< Internal unclassified error */
124 	UCL_ESSL,      /**< SSL error */
125 	UCL_EMERGE     /**< A merge error occurred */
126 } ucl_error_t;
127 
128 /**
129  * #ucl_object_t may have one of specified types, some types are compatible with each other and some are not.
130  * For example, you can always convert #UCL_TIME to #UCL_FLOAT. Also you can convert #UCL_FLOAT to #UCL_INTEGER
131  * by loosing floating point. Every object may be converted to a string by #ucl_object_tostring_forced() function.
132  *
133  */
134 typedef enum ucl_type {
135 	UCL_OBJECT = 0, /**< UCL object - key/value pairs */
136 	UCL_ARRAY,      /**< UCL array */
137 	UCL_INT,        /**< Integer number */
138 	UCL_FLOAT,      /**< Floating point number */
139 	UCL_STRING,     /**< Null terminated string */
140 	UCL_BOOLEAN,    /**< Boolean value */
141 	UCL_TIME,       /**< Time value (floating point number of seconds) */
142 	UCL_USERDATA,   /**< Opaque userdata pointer (may be used in macros) */
143 	UCL_NULL        /**< Null value */
144 } ucl_type_t;
145 
146 /**
147  * You can use one of these types to serialise #ucl_object_t by using ucl_object_emit().
148  */
149 typedef enum ucl_emitter {
150 	UCL_EMIT_JSON = 0,     /**< Emit fine formatted JSON */
151 	UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */
152 	UCL_EMIT_CONFIG,       /**< Emit human readable config format */
153 	UCL_EMIT_YAML,         /**< Emit embedded YAML format */
154 	UCL_EMIT_MSGPACK,      /**< Emit msgpack output */
155 	UCL_EMIT_MAX           /**< Unsupported emitter type */
156 } ucl_emitter_t;
157 
158 /**
159  * These flags defines parser behaviour. If you specify #UCL_PARSER_ZEROCOPY you must ensure
160  * that the input memory is not freed if an object is in use. Moreover, if you want to use
161  * zero-terminated keys and string values then you should not use zero-copy mode, as in this case
162  * UCL still has to perform copying implicitly.
163  */
164 typedef enum ucl_parser_flags {
165 	UCL_PARSER_DEFAULT = 0,                   /**< No special flags */
166 	UCL_PARSER_KEY_LOWERCASE = (1 << 0),      /**< Convert all keys to lower case */
167 	UCL_PARSER_ZEROCOPY = (1 << 1),           /**< Parse input in zero-copy mode if possible */
168 	UCL_PARSER_NO_TIME = (1 << 2),            /**< Do not parse time and treat time values as strings */
169 	UCL_PARSER_NO_IMPLICIT_ARRAYS = (1 << 3), /** Create explicit arrays instead of implicit ones */
170 	UCL_PARSER_SAVE_COMMENTS = (1 << 4),      /** Save comments in the parser context */
171 	UCL_PARSER_DISABLE_MACRO = (1 << 5),      /** Treat macros as comments */
172 	UCL_PARSER_NO_FILEVARS = (1 << 6)         /** Do not set file vars */
173 } ucl_parser_flags_t;
174 
175 /**
176  * String conversion flags, that are used in #ucl_object_fromstring_common function.
177  */
178 typedef enum ucl_string_flags {
179 	UCL_STRING_RAW = 0x0,                                                                             /**< Treat string as is */
180 	UCL_STRING_ESCAPE = (1 << 0),                                                                     /**< Perform JSON escape */
181 	UCL_STRING_TRIM = (1 << 1),                                                                       /**< Trim leading and trailing whitespaces */
182 	UCL_STRING_PARSE_BOOLEAN = (1 << 2),                                                              /**< Parse passed string and detect boolean */
183 	UCL_STRING_PARSE_INT = (1 << 3),                                                                  /**< Parse passed string and detect integer number */
184 	UCL_STRING_PARSE_DOUBLE = (1 << 4),                                                               /**< Parse passed string and detect integer or float number */
185 	UCL_STRING_PARSE_TIME = (1 << 5),                                                                 /**< Parse time strings */
186 	UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT | UCL_STRING_PARSE_DOUBLE | UCL_STRING_PARSE_TIME, /**<
187 									Parse passed string and detect number */
188 	UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN | UCL_STRING_PARSE_NUMBER,                            /**<
189 									Parse passed string (and detect booleans and numbers) */
190 	UCL_STRING_PARSE_BYTES = (1 << 6)                                                                 /**< Treat numbers as bytes */
191 } ucl_string_flags_t;
192 
193 /**
194  * Basic flags for an object (can use up to 12 bits as higher 4 bits are used
195  * for priorities)
196  */
197 typedef enum ucl_object_flags {
198 	UCL_OBJECT_ALLOCATED_KEY = (1 << 0),   /**< An object has key allocated internally */
199 	UCL_OBJECT_ALLOCATED_VALUE = (1 << 1), /**< An object has a string value allocated internally */
200 	UCL_OBJECT_NEED_KEY_ESCAPE = (1 << 2), /**< The key of an object need to be escaped on output */
201 	UCL_OBJECT_EPHEMERAL = (1 << 3),       /**< Temporary object that does not need to be freed really */
202 	UCL_OBJECT_MULTILINE = (1 << 4),       /**< String should be displayed as multiline string */
203 	UCL_OBJECT_MULTIVALUE = (1 << 5),      /**< Object is a key with multiple values */
204 	UCL_OBJECT_INHERITED = (1 << 6),       /**< Object has been inherited from another */
205 	UCL_OBJECT_BINARY = (1 << 7),          /**< Object contains raw binary data */
206 	UCL_OBJECT_SQUOTED = (1 << 8)          /**< Object has been enclosed in single quotes */
207 } ucl_object_flags_t;
208 
209 /**
210  * Duplicate policy types
211  */
212 enum ucl_duplicate_strategy {
213 	UCL_DUPLICATE_APPEND = 0, /**< Default policy to merge based on priorities */
214 	UCL_DUPLICATE_MERGE,      /**< Merge new object with old one */
215 	UCL_DUPLICATE_REWRITE,    /**< Rewrite old keys */
216 	UCL_DUPLICATE_ERROR       /**< Stop parsing on duplicate found */
217 };
218 
219 /**
220  * Input format type
221  */
222 enum ucl_parse_type {
223 	UCL_PARSE_UCL = 0, /**< Default ucl format */
224 	UCL_PARSE_MSGPACK, /**< Message pack input format */
225 	UCL_PARSE_CSEXP,   /**< Canonical S-expressions */
226 	UCL_PARSE_AUTO     /**< Try to detect parse type */
227 };
228 
229 /**
230  * UCL object structure. Please mention that the most of fields should not be touched by
231  * UCL users. In future, this structure may be converted to private one.
232  */
233 typedef struct ucl_object_s {
234 	/**
235 	 * Variant value type
236 	 */
237 	union {
238 		int64_t iv;     /**< Int value of an object */
239 		const char *sv; /**< String value of an object */
240 		double dv;      /**< Double value of an object */
241 		void *av;       /**< Array					*/
242 		void *ov;       /**< Object					*/
243 		void *ud;       /**< Opaque user data		*/
244 	} value;
245 	const char *key;               /**< Key of an object		*/
246 	struct ucl_object_s *next;     /**< Array handle			*/
247 	struct ucl_object_s *prev;     /**< Array handle			*/
248 	uint32_t keylen;               /**< Length of a key		*/
249 	uint32_t len;                  /**< Size of an object		*/
250 	uint32_t ref;                  /**< Reference count		*/
251 	uint16_t flags;                /**< Object flags			*/
252 	uint16_t type;                 /**< Real type				*/
253 	unsigned char *trash_stack[2]; /**< Pointer to allocated chunks */
254 } ucl_object_t;
255 
256 /**
257  * Destructor type for userdata objects
258  * @param ud user specified data pointer
259  */
260 typedef void (*ucl_userdata_dtor)(void *ud);
261 typedef const char *(*ucl_userdata_emitter)(void *ud);
262 
263 /** @} */
264 
265 /**
266  * @defgroup utils Utility functions
267  * A number of utility functions simplify handling of UCL objects
268  *
269  * @{
270  */
271 /**
272  * Copy and return a key of an object, returned key is zero-terminated
273  * @param obj CL object
274  * @return zero terminated key
275  */
276 UCL_EXTERN char *ucl_copy_key_trash(const ucl_object_t *obj);
277 
278 /**
279  * Copy and return a string value of an object, returned key is zero-terminated
280  * @param obj CL object
281  * @return zero terminated string representation of object value
282  */
283 UCL_EXTERN char *ucl_copy_value_trash(const ucl_object_t *obj);
284 
285 /**
286  * Creates a new object
287  * @return new object
288  */
289 UCL_EXTERN ucl_object_t *ucl_object_new(void) UCL_WARN_UNUSED_RESULT;
290 
291 /**
292  * Create new object with type specified
293  * @param type type of a new object
294  * @return new object
295  */
296 UCL_EXTERN ucl_object_t *ucl_object_typed_new(ucl_type_t type) UCL_WARN_UNUSED_RESULT;
297 
298 /**
299  * Create new object with type and priority specified
300  * @param type type of a new object
301  * @param priority priority of an object
302  * @return new object
303  */
304 UCL_EXTERN ucl_object_t *ucl_object_new_full(ucl_type_t type, unsigned priority)
305 	UCL_WARN_UNUSED_RESULT;
306 
307 /**
308  * Create new object with userdata dtor
309  * @param dtor destructor function
310  * @param emitter emitter for userdata
311  * @param ptr opaque pointer
312  * @return new object
313  */
314 UCL_EXTERN ucl_object_t *ucl_object_new_userdata(ucl_userdata_dtor dtor,
315 												 ucl_userdata_emitter emitter, void *ptr) UCL_WARN_UNUSED_RESULT;
316 
317 /**
318  * Perform deep copy of an object copying everything
319  * @param other object to copy
320  * @return new object with refcount equal to 1
321  */
322 UCL_EXTERN ucl_object_t *ucl_object_copy(const ucl_object_t *other)
323 	UCL_WARN_UNUSED_RESULT;
324 
325 /**
326  * Return the type of an object
327  * @return the object type
328  */
329 UCL_EXTERN ucl_type_t ucl_object_type(const ucl_object_t *obj);
330 
331 /**
332  * Converts ucl object type to its string representation
333  * @param type type of object
334  * @return constant string describing type
335  */
336 UCL_EXTERN const char *ucl_object_type_to_string(ucl_type_t type);
337 
338 /**
339  * Converts string that represents ucl type to real ucl type enum
340  * @param input C string with name of type
341  * @param res resulting target
342  * @return true if `input` is a name of type stored in `res`
343  */
344 UCL_EXTERN bool ucl_object_string_to_type(const char *input, ucl_type_t *res);
345 
346 /**
347  * Convert any string to an ucl object making the specified transformations
348  * @param str fixed size or NULL terminated string
349  * @param len length (if len is zero, than str is treated as NULL terminated)
350  * @param flags conversion flags
351  * @return new object
352  */
353 UCL_EXTERN ucl_object_t *ucl_object_fromstring_common(const char *str, size_t len,
354 													  enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT;
355 
356 /**
357  * Create a UCL object from the specified string
358  * @param str NULL terminated string, will be json escaped
359  * @return new object
360  */
361 UCL_EXTERN ucl_object_t *ucl_object_fromstring(const char *str) UCL_WARN_UNUSED_RESULT;
362 
363 /**
364  * Create a UCL object from the specified string
365  * @param str fixed size string, will be json escaped
366  * @param len length of a string
367  * @return new object
368  */
369 UCL_EXTERN ucl_object_t *ucl_object_fromlstring(const char *str,
370 												size_t len) UCL_WARN_UNUSED_RESULT;
371 
372 /**
373  * Create an object from an integer number
374  * @param iv number
375  * @return new object
376  */
377 UCL_EXTERN ucl_object_t *ucl_object_fromint(int64_t iv) UCL_WARN_UNUSED_RESULT;
378 
379 /**
380  * Create an object from a float number
381  * @param dv number
382  * @return new object
383  */
384 UCL_EXTERN ucl_object_t *ucl_object_fromdouble(double dv) UCL_WARN_UNUSED_RESULT;
385 
386 /**
387  * Create an object from a boolean
388  * @param bv bool value
389  * @return new object
390  */
391 UCL_EXTERN ucl_object_t *ucl_object_frombool(bool bv) UCL_WARN_UNUSED_RESULT;
392 
393 /**
394  * Insert a object 'elt' to the hash 'top' and associate it with key 'key'
395  * @param top destination object (must be of type UCL_OBJECT)
396  * @param elt element to insert (must NOT be NULL)
397  * @param key key to associate with this object (either const or preallocated)
398  * @param keylen length of the key (or 0 for NULL terminated keys)
399  * @param copy_key make an internal copy of key
400  * @return true if key has been inserted
401  */
402 UCL_EXTERN bool ucl_object_insert_key(ucl_object_t *top, ucl_object_t *elt,
403 									  const char *key, size_t keylen, bool copy_key);
404 
405 /**
406  * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed,
407  * if no object has been found this function works like ucl_object_insert_key()
408  * @param top destination object (must be of type UCL_OBJECT)
409  * @param elt element to insert (must NOT be NULL)
410  * @param key key to associate with this object (either const or preallocated)
411  * @param keylen length of the key (or 0 for NULL terminated keys)
412  * @param copy_key make an internal copy of key
413  * @return true if key has been inserted
414  */
415 UCL_EXTERN bool ucl_object_replace_key(ucl_object_t *top, ucl_object_t *elt,
416 									   const char *key, size_t keylen, bool copy_key);
417 
418 /**
419  * Merge the keys from one object to another object. Overwrite on conflict
420  * @param top destination object (must be of type UCL_OBJECT)
421  * @param elt element to insert (must be of type UCL_OBJECT)
422  * @param copy copy rather than reference the elements
423  * @return true if all keys have been merged
424  */
425 UCL_EXTERN bool ucl_object_merge(ucl_object_t *top, ucl_object_t *elt, bool copy);
426 
427 /**
428  * Delete a object associated with key 'key', old object will be unrefered,
429  * @param top object
430  * @param key key associated to the object to remove
431  * @param keylen length of the key (or 0 for NULL terminated keys)
432  */
433 UCL_EXTERN bool ucl_object_delete_keyl(ucl_object_t *top,
434 									   const char *key, size_t keylen);
435 
436 /**
437  * Delete a object associated with key 'key', old object will be unrefered,
438  * @param top object
439  * @param key key associated to the object to remove
440  */
441 UCL_EXTERN bool ucl_object_delete_key(ucl_object_t *top,
442 									  const char *key);
443 
444 
445 /**
446  * Removes `key` from `top` object, returning the object that was removed. This
447  * object is not released, caller must unref the returned object when it is no
448  * longer needed.
449  * @param top object
450  * @param key key to remove
451  * @param keylen length of the key (or 0 for NULL terminated keys)
452  * @return removed object or NULL if object has not been found
453  */
454 UCL_EXTERN ucl_object_t *ucl_object_pop_keyl(ucl_object_t *top, const char *key,
455 											 size_t keylen) UCL_WARN_UNUSED_RESULT;
456 
457 /**
458  * Removes `key` from `top` object returning the object that was removed. This
459  * object is not released, caller must unref the returned object when it is no
460  * longer needed.
461  * @param top object
462  * @param key key to remove
463  * @return removed object or NULL if object has not been found
464  */
465 UCL_EXTERN ucl_object_t *ucl_object_pop_key(ucl_object_t *top, const char *key)
466 	UCL_WARN_UNUSED_RESULT;
467 
468 /**
469  * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if
470  * the specified key exist, try to merge its content
471  * @param top destination object (must be of type UCL_OBJECT)
472  * @param elt element to insert (must NOT be NULL)
473  * @param key key to associate with this object (either const or preallocated)
474  * @param keylen length of the key (or 0 for NULL terminated keys)
475  * @param copy_key make an internal copy of key
476  * @return true if key has been inserted
477  */
478 UCL_EXTERN bool ucl_object_insert_key_merged(ucl_object_t *top, ucl_object_t *elt,
479 											 const char *key, size_t keylen, bool copy_key);
480 
481 /**
482  * Reserve space in ucl array or object for `elt` elements
483  * @param obj object to reserve
484  * @param reserved size to reserve in an object
485  * @return 0 on success, -1 on failure (i.e. ENOMEM)
486  */
487 UCL_EXTERN bool ucl_object_reserve(ucl_object_t *obj, size_t reserved);
488 
489 /**
490  * Append an element to the end of array object
491  * @param top destination object (must NOT be NULL)
492  * @param elt element to append (must NOT be NULL)
493  * @return true if value has been inserted
494  */
495 UCL_EXTERN bool ucl_array_append(ucl_object_t *top,
496 								 ucl_object_t *elt);
497 
498 /**
499  * Append an element to the start of array object
500  * @param top destination object (must NOT be NULL)
501  * @param elt element to append (must NOT be NULL)
502  * @return true if value has been inserted
503  */
504 UCL_EXTERN bool ucl_array_prepend(ucl_object_t *top,
505 								  ucl_object_t *elt);
506 
507 /**
508  * Merge all elements of second array into the first array
509  * @param top destination array (must be of type UCL_ARRAY)
510  * @param elt array to copy elements from (must be of type UCL_ARRAY)
511  * @param copy copy elements instead of referencing them
512  * @return true if arrays were merged
513  */
514 UCL_EXTERN bool ucl_array_merge(ucl_object_t *top, ucl_object_t *elt,
515 								bool copy);
516 
517 /**
518  * Removes an element `elt` from the array `top`, returning the object that was
519  * removed. This object is not released, caller must unref the returned object
520  * when it is no longer needed.
521  * @param top array ucl object
522  * @param elt element to remove
523  * @return removed element or NULL if `top` is NULL or not an array
524  */
525 UCL_EXTERN ucl_object_t *ucl_array_delete(ucl_object_t *top,
526 										  ucl_object_t *elt);
527 
528 /**
529  * Returns the first element of the array `top`
530  * @param top array ucl object
531  * @return element or NULL if `top` is NULL or not an array
532  */
533 UCL_EXTERN const ucl_object_t *ucl_array_head(const ucl_object_t *top);
534 
535 /**
536  * Returns the last element of the array `top`
537  * @param top array ucl object
538  * @return element or NULL if `top` is NULL or not an array
539  */
540 UCL_EXTERN const ucl_object_t *ucl_array_tail(const ucl_object_t *top);
541 
542 /**
543  * Removes the last element from the array `top`, returning the object that was
544  * removed. This object is not released, caller must unref the returned object
545  * when it is no longer needed.
546  * @param top array ucl object
547  * @return removed element or NULL if `top` is NULL or not an array
548  */
549 UCL_EXTERN ucl_object_t *ucl_array_pop_last(ucl_object_t *top);
550 
551 /**
552  * Removes the first element from the array `top`, returning the object that was
553  * removed. This object is not released, caller must unref the returned object
554  * when it is no longer needed.
555  * @param top array ucl object
556  * @return removed element or NULL if `top` is NULL or not an array
557  */
558 UCL_EXTERN ucl_object_t *ucl_array_pop_first(ucl_object_t *top);
559 
560 /**
561  * Return size of the array `top`
562  * @param top object to get size from (must be of type UCL_ARRAY)
563  * @return size of the array
564  */
565 UCL_EXTERN unsigned int ucl_array_size(const ucl_object_t *top);
566 
567 /**
568  * Return object identified by index of the array `top`
569  * @param top object to get a key from (must be of type UCL_ARRAY)
570  * @param index array index to return
571  * @return object at the specified index or NULL if index is not found
572  */
573 UCL_EXTERN const ucl_object_t *ucl_array_find_index(const ucl_object_t *top,
574 													unsigned int index);
575 
576 /**
577  * Return the index of `elt` in the array `top`
578  * @param top object to get a key from (must be of type UCL_ARRAY)
579  * @param elt element to find index of (must NOT be NULL)
580  * @return index of `elt` in the array `top or (unsigned int)-1 if `elt` is not found
581  */
582 UCL_EXTERN unsigned int ucl_array_index_of(ucl_object_t *top,
583 										   ucl_object_t *elt);
584 
585 /**
586  * Replace an element in an array with a different element, returning the object
587  * that was replaced. This object is not released, caller must unref the
588  * returned object when it is no longer needed.
589  * @param top destination object (must be of type UCL_ARRAY)
590  * @param elt element to append (must NOT be NULL)
591  * @param index array index in destination to overwrite with elt
592  * @return object that was replaced or NULL if index is not found
593  */
594 ucl_object_t *
595 ucl_array_replace_index(ucl_object_t *top, ucl_object_t *elt,
596 						unsigned int index);
597 
598 /**
599  * Append a element to another element forming an implicit array
600  * @param head head to append (may be NULL)
601  * @param elt new element
602  * @return the new implicit array
603  */
604 UCL_EXTERN ucl_object_t *ucl_elt_append(ucl_object_t *head,
605 										ucl_object_t *elt);
606 
607 /**
608  * Converts an object to double value
609  * @param obj CL object
610  * @param target target double variable
611  * @return true if conversion was successful
612  */
613 UCL_EXTERN bool ucl_object_todouble_safe(const ucl_object_t *obj, double *target);
614 
615 /**
616  * Unsafe version of \ref ucl_obj_todouble_safe
617  * @param obj CL object
618  * @return double value
619  */
620 UCL_EXTERN double ucl_object_todouble(const ucl_object_t *obj);
621 
622 /**
623  * Converts an object to integer value
624  * @param obj CL object
625  * @param target target integer variable
626  * @return true if conversion was successful
627  */
628 UCL_EXTERN bool ucl_object_toint_safe(const ucl_object_t *obj, int64_t *target);
629 
630 /**
631  * Unsafe version of \ref ucl_obj_toint_safe
632  * @param obj CL object
633  * @return int value
634  */
635 UCL_EXTERN int64_t ucl_object_toint(const ucl_object_t *obj);
636 
637 /**
638  * Converts an object to boolean value
639  * @param obj CL object
640  * @param target target boolean variable
641  * @return true if conversion was successful
642  */
643 UCL_EXTERN bool ucl_object_toboolean_safe(const ucl_object_t *obj, bool *target);
644 
645 /**
646  * Unsafe version of \ref ucl_obj_toboolean_safe
647  * @param obj CL object
648  * @return boolean value
649  */
650 UCL_EXTERN bool ucl_object_toboolean(const ucl_object_t *obj);
651 
652 /**
653  * Converts an object to string value
654  * @param obj CL object
655  * @param target target string variable, no need to free value
656  * @return true if conversion was successful
657  */
658 UCL_EXTERN bool ucl_object_tostring_safe(const ucl_object_t *obj, const char **target);
659 
660 /**
661  * Unsafe version of \ref ucl_obj_tostring_safe
662  * @param obj CL object
663  * @return string value
664  */
665 UCL_EXTERN const char *ucl_object_tostring(const ucl_object_t *obj);
666 
667 /**
668  * Convert any object to a string in JSON notation if needed
669  * @param obj CL object
670  * @return string value
671  */
672 UCL_EXTERN const char *ucl_object_tostring_forced(const ucl_object_t *obj);
673 
674 /**
675  * Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it
676  * allows zero-copy (if #UCL_PARSER_ZEROCOPY has been used during parsing)
677  * @param obj CL object
678  * @param target target string variable, no need to free value
679  * @param tlen target length
680  * @return true if conversion was successful
681  */
682 UCL_EXTERN bool ucl_object_tolstring_safe(const ucl_object_t *obj,
683 										  const char **target, size_t *tlen);
684 
685 /**
686  * Unsafe version of \ref ucl_obj_tolstring_safe
687  * @param obj CL object
688  * @return string value
689  */
690 UCL_EXTERN const char *ucl_object_tolstring(const ucl_object_t *obj, size_t *tlen);
691 
692 /**
693  * Return object identified by a key in the specified object
694  * @param obj object to get a key from (must be of type UCL_OBJECT)
695  * @param key key to search
696  * @return object matching the specified key or NULL if key was not found
697  */
698 UCL_EXTERN const ucl_object_t *ucl_object_lookup(const ucl_object_t *obj,
699 												 const char *key);
700 #define ucl_object_find_key ucl_object_lookup
701 
702 /**
703  * Return object identified by a key in the specified object, if the first key is
704  * not found then look for the next one. This process is repeated unless
705  * the next argument in the list is not NULL. So, `ucl_object_find_any_key(obj, key, NULL)`
706  * is equal to `ucl_object_find_key(obj, key)`
707  * @param obj object to get a key from (must be of type UCL_OBJECT)
708  * @param key key to search
709  * @param ... list of alternative keys to search (NULL terminated)
710  * @return object matching the specified key or NULL if key was not found
711  */
712 UCL_EXTERN const ucl_object_t *ucl_object_lookup_any(const ucl_object_t *obj,
713 													 const char *key, ...);
714 #define ucl_object_find_any_key ucl_object_lookup_any
715 
716 /**
717  * Return object identified by a fixed size key in the specified object
718  * @param obj object to get a key from (must be of type UCL_OBJECT)
719  * @param key key to search
720  * @param klen length of a key
721  * @return object matching the specified key or NULL if key was not found
722  */
723 UCL_EXTERN const ucl_object_t *ucl_object_lookup_len(const ucl_object_t *obj,
724 													 const char *key, size_t klen);
725 #define ucl_object_find_keyl ucl_object_lookup_len
726 
727 /**
728  * Return object identified by dot notation string
729  * @param obj object to search in
730  * @param path dot.notation.path to the path to lookup. May use numeric .index on arrays
731  * @return object matched the specified path or NULL if path is not found
732  */
733 UCL_EXTERN const ucl_object_t *ucl_object_lookup_path(const ucl_object_t *obj,
734 													  const char *path);
735 #define ucl_lookup_path ucl_object_lookup_path
736 
737 /**
738  * Return object identified by object notation string using arbitrary delimiter
739  * @param obj object to search in
740  * @param path dot.notation.path to the path to lookup. May use numeric .index on arrays
741  * @param sep the sepatorator to use in place of . (incase keys have . in them)
742  * @return object matched the specified path or NULL if path is not found
743  */
744 UCL_EXTERN const ucl_object_t *ucl_object_lookup_path_char(const ucl_object_t *obj,
745 														   const char *path, char sep);
746 #define ucl_lookup_path_char ucl_object_lookup_path_char
747 
748 /**
749  * Returns a key of an object as a NULL terminated string
750  * @param obj CL object
751  * @return key or NULL if there is no key
752  */
753 UCL_EXTERN const char *ucl_object_key(const ucl_object_t *obj);
754 
755 /**
756  * Returns a key of an object as a fixed size string (may be more efficient)
757  * @param obj CL object
758  * @param len target key length
759  * @return key pointer
760  */
761 UCL_EXTERN const char *ucl_object_keyl(const ucl_object_t *obj, size_t *len);
762 
763 /**
764  * Increase reference count for an object
765  * @param obj object to ref
766  * @return the referenced object
767  */
768 UCL_EXTERN ucl_object_t *ucl_object_ref(const ucl_object_t *obj);
769 
770 /**
771  * Free ucl object
772  * @param obj ucl object to free
773  */
774 UCL_DEPRECATED(UCL_EXTERN void ucl_object_free(ucl_object_t *obj));
775 
776 /**
777  * Decrease reference count for an object
778  * @param obj object to unref
779  */
780 UCL_EXTERN void ucl_object_unref(ucl_object_t *obj);
781 
782 /**
783  * Compare objects `o1` and `o2`
784  * @param o1 the first object
785  * @param o2 the second object
786  * @return values >0, 0 and <0 if `o1` is more than, equal and less than `o2`.
787  * The order of comparison:
788  * 1) Type of objects
789  * 2) Size of objects
790  * 3) Content of objects
791  */
792 UCL_EXTERN int ucl_object_compare(const ucl_object_t *o1,
793 								  const ucl_object_t *o2);
794 
795 /**
796  * Compare objects `o1` and `o2` useful for sorting
797  * @param o1 the first object
798  * @param o2 the second object
799  * @return values >0, 0 and <0 if `o1` is more than, equal and less than `o2`.
800  * The order of comparison:
801  * 1) Type of objects
802  * 2) Size of objects
803  * 3) Content of objects
804  */
805 UCL_EXTERN int ucl_object_compare_qsort(const ucl_object_t **o1,
806 										const ucl_object_t **o2);
807 
808 /**
809  * Sort UCL array using `cmp` compare function
810  * @param ar
811  * @param cmp
812  */
813 UCL_EXTERN void ucl_object_array_sort(ucl_object_t *ar,
814 									  int (*cmp)(const ucl_object_t **o1, const ucl_object_t **o2));
815 
816 enum ucl_object_keys_sort_flags {
817 	UCL_SORT_KEYS_DEFAULT = 0,
818 	UCL_SORT_KEYS_ICASE = (1u << 0u),
819 	UCL_SORT_KEYS_RECURSIVE = (1u << 1u),
820 };
821 /***
822  * Sorts keys in object in place
823  * @param obj
824  * @param how
825  */
826 UCL_EXTERN void ucl_object_sort_keys(ucl_object_t *obj,
827 									 enum ucl_object_keys_sort_flags how);
828 
829 /**
830  * Get the priority for specific UCL object
831  * @param obj any ucl object
832  * @return priority of an object
833  */
834 UCL_EXTERN unsigned int ucl_object_get_priority(const ucl_object_t *obj);
835 
836 /**
837  * Set explicit priority of an object.
838  * @param obj any ucl object
839  * @param priority new priroity value (only 4 least significant bits are considred)
840  */
841 UCL_EXTERN void ucl_object_set_priority(ucl_object_t *obj,
842 										unsigned int priority);
843 
844 /**
845  * Opaque iterator object
846  */
847 typedef void *ucl_object_iter_t;
848 
849 /**
850  * Get next key from an object
851  * @param obj object to iterate
852  * @param iter opaque iterator, must be set to NULL on the first call:
853  * ucl_object_iter_t it = NULL;
854  * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ...
855  * @param ep pointer record exception (such as ENOMEM), could be NULL
856  * @return the next object or NULL
857  */
858 UCL_EXTERN const ucl_object_t *ucl_object_iterate_with_error(const ucl_object_t *obj,
859 															 ucl_object_iter_t *iter, bool expand_values, int *ep);
860 
861 #define ucl_iterate_object ucl_object_iterate
862 #define ucl_object_iterate(ob, it, ev) ucl_object_iterate_with_error((ob), (it), (ev), NULL)
863 
864 /**
865  * Create new safe iterator for the specified object
866  * @param obj object to iterate
867  * @return new iterator object that should be used with safe iterators API only
868  */
869 UCL_EXTERN ucl_object_iter_t ucl_object_iterate_new(const ucl_object_t *obj)
870 	UCL_WARN_UNUSED_RESULT;
871 /**
872  * Check safe iterator object after performing some operations on it
873  * (such as ucl_object_iterate_safe()) to see if operation has encountered
874  * fatal exception while performing that operation (e.g. ENOMEM).
875  * @param iter opaque iterator
876  * @return true if exception has occured, false otherwise
877  */
878 UCL_EXTERN bool ucl_object_iter_chk_excpn(ucl_object_iter_t *it);
879 
880 /**
881  * Reset initialized iterator to a new object
882  * @param obj new object to iterate
883  * @return modified iterator object
884  */
885 UCL_EXTERN ucl_object_iter_t ucl_object_iterate_reset(ucl_object_iter_t it,
886 													  const ucl_object_t *obj);
887 
888 /**
889  * Get the next object from the `obj`. This function iterates over arrays, objects
890  * and implicit arrays
891  * @param iter safe iterator
892  * @param expand_values expand explicit arrays and objects
893  * @return the next object in sequence
894  */
895 UCL_EXTERN const ucl_object_t *ucl_object_iterate_safe(ucl_object_iter_t iter,
896 													   bool expand_values);
897 /**
898  * Iteration type enumerator
899  */
900 enum ucl_iterate_type {
901 	UCL_ITERATE_EXPLICIT = 1 << 0,          /**< Iterate just explicit arrays and objects */
902 	UCL_ITERATE_IMPLICIT = 1 << 1,          /**< Iterate just implicit arrays */
903 	UCL_ITERATE_BOTH = (1 << 0) | (1 << 1), /**< Iterate both explicit and implicit arrays*/
904 };
905 
906 /**
907  * Get the next object from the `obj`. This function iterates over arrays, objects
908  * and implicit arrays if needed
909  * @param iter safe iterator
910  * @param
911  * @return the next object in sequence
912  */
913 UCL_EXTERN const ucl_object_t *ucl_object_iterate_full(ucl_object_iter_t iter,
914 													   enum ucl_iterate_type type);
915 
916 /**
917  * Free memory associated with the safe iterator
918  * @param it safe iterator object
919  */
920 UCL_EXTERN void ucl_object_iterate_free(ucl_object_iter_t it);
921 
922 /** @} */
923 
924 
925 /**
926  * @defgroup parser Parsing functions
927  * These functions are used to parse UCL objects
928  *
929  * @{
930  */
931 
932 /**
933  * Macro handler for a parser
934  * @param data the content of macro
935  * @param len the length of content
936  * @param arguments arguments object
937  * @param ud opaque user data
938  * @param err error pointer
939  * @return true if macro has been parsed
940  */
941 typedef bool (*ucl_macro_handler)(const unsigned char *data, size_t len,
942 								  const ucl_object_t *arguments,
943 								  void *ud);
944 
945 /**
946  * Context dependent macro handler for a parser
947  * @param data the content of macro
948  * @param len the length of content
949  * @param arguments arguments object
950  * @param context previously parsed context
951  * @param ud opaque user data
952  * @param err error pointer
953  * @return true if macro has been parsed
954  */
955 typedef bool (*ucl_context_macro_handler)(const unsigned char *data, size_t len,
956 										  const ucl_object_t *arguments,
957 										  const ucl_object_t *context,
958 										  void *ud);
959 
960 /* Opaque parser */
961 struct ucl_parser;
962 
963 /**
964  * Creates new parser object
965  * @param pool pool to allocate memory from
966  * @return new parser object
967  */
968 UCL_EXTERN struct ucl_parser *ucl_parser_new(int flags);
969 
970 /**
971  * Sets the default priority for the parser applied to chunks that do not
972  * specify priority explicitly
973  * @param parser parser object
974  * @param prio default priority (0 .. 16)
975  * @return true if parser's default priority was set
976  */
977 UCL_EXTERN bool ucl_parser_set_default_priority(struct ucl_parser *parser,
978 												unsigned prio);
979 /**
980  * Gets the default priority for the parser applied to chunks that do not
981  * specify priority explicitly
982  * @param parser parser object
983  * @return true default priority (0 .. 16), -1 for failure
984  */
985 UCL_EXTERN int ucl_parser_get_default_priority(struct ucl_parser *parser);
986 
987 /**
988  * Register new handler for a macro
989  * @param parser parser object
990  * @param macro macro name (without leading dot)
991  * @param handler handler (it is called immediately after macro is parsed)
992  * @param ud opaque user data for a handler
993  * @return true on success, false on failure (i.e. ENOMEM)
994  */
995 UCL_EXTERN bool ucl_parser_register_macro(struct ucl_parser *parser,
996 										  const char *macro,
997 										  ucl_macro_handler handler, void *ud);
998 
999 /**
1000  * Register new context dependent handler for a macro
1001  * @param parser parser object
1002  * @param macro macro name (without leading dot)
1003  * @param handler handler (it is called immediately after macro is parsed)
1004  * @param ud opaque user data for a handler
1005  * @return true on success, false on failure (i.e. ENOMEM)
1006  */
1007 UCL_EXTERN bool ucl_parser_register_context_macro(struct ucl_parser *parser,
1008 												  const char *macro,
1009 												  ucl_context_macro_handler handler,
1010 												  void *ud);
1011 
1012 /**
1013  * Handler to detect unregistered variables
1014  * @param data variable data
1015  * @param len length of variable
1016  * @param replace (out) replace value for variable
1017  * @param replace_len (out) replace length for variable
1018  * @param need_free (out) UCL will free `dest` after usage
1019  * @param ud opaque userdata
1020  * @return true if variable
1021  */
1022 typedef bool (*ucl_variable_handler)(const unsigned char *data, size_t len,
1023 									 unsigned char **replace, size_t *replace_len, bool *need_free, void *ud);
1024 
1025 /**
1026  * Register new parser variable
1027  * @param parser parser object
1028  * @param var variable name
1029  * @param value variable value
1030  */
1031 UCL_EXTERN void ucl_parser_register_variable(struct ucl_parser *parser, const char *var,
1032 											 const char *value);
1033 
1034 /**
1035  * Set handler for unknown variables
1036  * @param parser parser structure
1037  * @param handler desired handler
1038  * @param ud opaque data for the handler
1039  */
1040 UCL_EXTERN void ucl_parser_set_variables_handler(struct ucl_parser *parser,
1041 												 ucl_variable_handler handler, void *ud);
1042 
1043 /**
1044  * Load new chunk to a parser
1045  * @param parser parser structure
1046  * @param data the pointer to the beginning of a chunk
1047  * @param len the length of a chunk
1048  * @return true if chunk has been added and false in case of error
1049  */
1050 UCL_EXTERN bool ucl_parser_add_chunk(struct ucl_parser *parser,
1051 									 const unsigned char *data, size_t len);
1052 
1053 /**
1054  * Load new chunk to a parser with the specified priority
1055  * @param parser parser structure
1056  * @param data the pointer to the beginning of a chunk
1057  * @param len the length of a chunk
1058  * @param priority the desired priority of a chunk (only 4 least significant bits
1059  * are considered for this parameter)
1060  * @return true if chunk has been added and false in case of error
1061  */
1062 UCL_EXTERN bool ucl_parser_add_chunk_priority(struct ucl_parser *parser,
1063 											  const unsigned char *data, size_t len, unsigned priority);
1064 
1065 /**
1066  * Insert new chunk to a parser (must have previously processed data with an existing top object)
1067  * @param parser parser structure
1068  * @param data the pointer to the beginning of a chunk
1069  * @param len the length of a chunk
1070  * @return true if chunk has been added and false in case of error
1071  */
1072 UCL_EXTERN bool ucl_parser_insert_chunk(struct ucl_parser *parser,
1073 										const unsigned char *data, size_t len);
1074 
1075 /**
1076  * Full version of ucl_add_chunk with priority and duplicate strategy
1077  * @param parser parser structure
1078  * @param data the pointer to the beginning of a chunk
1079  * @param len the length of a chunk
1080  * @param priority the desired priority of a chunk (only 4 least significant bits
1081  * are considered for this parameter)
1082  * @param strat duplicates merging strategy
1083  * @param parse_type input format
1084  * @return true if chunk has been added and false in case of error
1085  */
1086 UCL_EXTERN bool ucl_parser_add_chunk_full(struct ucl_parser *parser,
1087 										  const unsigned char *data, size_t len, unsigned priority,
1088 										  enum ucl_duplicate_strategy strat, enum ucl_parse_type parse_type);
1089 
1090 /**
1091  * Load ucl object from a string
1092  * @param parser parser structure
1093  * @param data the pointer to the string
1094  * @param len the length of the string, if `len` is 0 then `data` must be zero-terminated string
1095  * @return true if string has been added and false in case of error
1096  */
1097 UCL_EXTERN bool ucl_parser_add_string(struct ucl_parser *parser,
1098 									  const char *data, size_t len);
1099 
1100 /**
1101  * Load ucl object from a string
1102  * @param parser parser structure
1103  * @param data the pointer to the string
1104  * @param len the length of the string, if `len` is 0 then `data` must be zero-terminated string
1105  * @param priority the desired priority of a chunk (only 4 least significant bits
1106  * are considered for this parameter)
1107  * @return true if string has been added and false in case of error
1108  */
1109 UCL_EXTERN bool ucl_parser_add_string_priority(struct ucl_parser *parser,
1110 											   const char *data, size_t len, unsigned priority);
1111 
1112 /**
1113  * Load and add data from a file
1114  * @param parser parser structure
1115  * @param filename the name of file
1116  * @param err if *err is NULL it is set to parser error
1117  * @return true if chunk has been added and false in case of error
1118  */
1119 UCL_EXTERN bool ucl_parser_add_file(struct ucl_parser *parser,
1120 									const char *filename);
1121 
1122 /**
1123  * Load and add data from a file
1124  * @param parser parser structure
1125  * @param filename the name of file
1126  * @param err if *err is NULL it is set to parser error
1127  * @param priority the desired priority of a chunk (only 4 least significant bits
1128  * are considered for this parameter)
1129  * @return true if chunk has been added and false in case of error
1130  */
1131 UCL_EXTERN bool ucl_parser_add_file_priority(struct ucl_parser *parser,
1132 											 const char *filename, unsigned priority);
1133 
1134 /**
1135  * Load and add data from a file
1136  * @param parser parser structure
1137  * @param filename the name of file
1138  * @param priority the desired priority of a chunk (only 4 least significant bits
1139  * are considered for this parameter)
1140  * @param strat Merge strategy to use while parsing this file
1141  * @param parse_type Parser type to use while parsing this file
1142  * @return true if chunk has been added and false in case of error
1143  */
1144 UCL_EXTERN bool ucl_parser_add_file_full(struct ucl_parser *parser, const char *filename,
1145 										 unsigned priority, enum ucl_duplicate_strategy strat,
1146 										 enum ucl_parse_type parse_type);
1147 
1148 /**
1149  * Load and add data from a file descriptor
1150  * @param parser parser structure
1151  * @param filename the name of file
1152  * @param err if *err is NULL it is set to parser error
1153  * @return true if chunk has been added and false in case of error
1154  */
1155 UCL_EXTERN bool ucl_parser_add_fd(struct ucl_parser *parser,
1156 								  int fd);
1157 
1158 /**
1159  * Load and add data from a file descriptor
1160  * @param parser parser structure
1161  * @param filename the name of file
1162  * @param err if *err is NULL it is set to parser error
1163  * @param priority the desired priority of a chunk (only 4 least significant bits
1164  * are considered for this parameter)
1165  * @return true if chunk has been added and false in case of error
1166  */
1167 UCL_EXTERN bool ucl_parser_add_fd_priority(struct ucl_parser *parser,
1168 										   int fd, unsigned priority);
1169 
1170 /**
1171  * Load and add data from a file descriptor
1172  * @param parser parser structure
1173  * @param filename the name of file
1174  * @param err if *err is NULL it is set to parser error
1175  * @param priority the desired priority of a chunk (only 4 least significant bits
1176  * are considered for this parameter)
1177  * @param strat Merge strategy to use while parsing this file
1178  * @param parse_type Parser type to use while parsing this file
1179  * @return true if chunk has been added and false in case of error
1180  */
1181 UCL_EXTERN bool ucl_parser_add_fd_full(struct ucl_parser *parser, int fd,
1182 									   unsigned priority, enum ucl_duplicate_strategy strat,
1183 									   enum ucl_parse_type parse_type);
1184 
1185 /**
1186  * Provide a UCL_ARRAY of paths to search for include files. The object is
1187  * copied so caller must unref the object.
1188  * @param parser parser structure
1189  * @param paths UCL_ARRAY of paths to search
1190  * @return true if the path search array was replaced in the parser
1191  */
1192 UCL_EXTERN bool ucl_set_include_path(struct ucl_parser *parser,
1193 									 ucl_object_t *paths);
1194 
1195 /**
1196  * Get a top object for a parser (refcount is increased)
1197  * @param parser parser structure
1198  * @param err if *err is NULL it is set to parser error
1199  * @return top parser object or NULL
1200  */
1201 UCL_EXTERN ucl_object_t *ucl_parser_get_object(struct ucl_parser *parser);
1202 
1203 /**
1204  * Get the current stack object as stack accessor function for use in macro
1205  * functions (refcount is increased)
1206  * @param parser parser object
1207  * @param depth depth of stack to retrieve (top is 0)
1208  * @return current stack object or NULL
1209  */
1210 UCL_EXTERN ucl_object_t *ucl_parser_get_current_stack_object(struct ucl_parser *parser, unsigned int depth);
1211 
1212 /**
1213  * Peek at the character at the current chunk position
1214  * @param parser parser structure
1215  * @return current chunk position character
1216  */
1217 UCL_EXTERN unsigned char ucl_parser_chunk_peek(struct ucl_parser *parser);
1218 
1219 /**
1220  * Skip the character at the current chunk position
1221  * @param parser parser structure
1222  * @return success boolean
1223  */
1224 UCL_EXTERN bool ucl_parser_chunk_skip(struct ucl_parser *parser);
1225 
1226 /**
1227  * Get the error string if parsing has been failed
1228  * @param parser parser object
1229  * @return error description
1230  */
1231 UCL_EXTERN const char *ucl_parser_get_error(struct ucl_parser *parser);
1232 
1233 /**
1234  * Get the code of the last error
1235  * @param parser parser object
1236  * @return error code
1237  */
1238 UCL_EXTERN int ucl_parser_get_error_code(struct ucl_parser *parser);
1239 
1240 /**
1241  * Get the current column number within parser
1242  * @param parser parser object
1243  * @return current column number
1244  */
1245 UCL_EXTERN unsigned ucl_parser_get_column(struct ucl_parser *parser);
1246 
1247 /**
1248  * Get the current line number within parser
1249  * @param parser parser object
1250  * @return current line number
1251  */
1252 UCL_EXTERN unsigned ucl_parser_get_linenum(struct ucl_parser *parser);
1253 
1254 /**
1255  * Clear the error in the parser
1256  * @param parser parser object
1257  */
1258 UCL_EXTERN void ucl_parser_clear_error(struct ucl_parser *parser);
1259 
1260 /**
1261  * Free ucl parser object
1262  * @param parser parser object
1263  */
1264 UCL_EXTERN void ucl_parser_free(struct ucl_parser *parser);
1265 
1266 /**
1267  * Get constant opaque pointer to comments structure for this parser. Increase
1268  * refcount to prevent this object to be destroyed on parser's destruction
1269  * @param parser parser structure
1270  * @return ucl comments pointer or NULL
1271  */
1272 UCL_EXTERN const ucl_object_t *ucl_parser_get_comments(struct ucl_parser *parser);
1273 
1274 /**
1275  * Utility function to find a comment object for the specified object in the input
1276  * @param comments comments object
1277  * @param srch search object
1278  * @return string comment enclosed in ucl_object_t
1279  */
1280 UCL_EXTERN const ucl_object_t *ucl_comments_find(const ucl_object_t *comments,
1281 												 const ucl_object_t *srch);
1282 
1283 /**
1284  * Move comment from `from` object to `to` object
1285  * @param comments comments object
1286  * @param what source object
1287  * @param with destination object
1288  * @return `true` if `from` has comment and it has been moved to `to`
1289  */
1290 UCL_EXTERN bool ucl_comments_move(ucl_object_t *comments,
1291 								  const ucl_object_t *from, const ucl_object_t *to);
1292 
1293 /**
1294  * Adds a new comment for an object
1295  * @param comments comments object
1296  * @param obj object to add comment to
1297  * @param comment string representation of a comment
1298  */
1299 UCL_EXTERN void ucl_comments_add(ucl_object_t *comments,
1300 								 const ucl_object_t *obj, const char *comment);
1301 
1302 /**
1303  * Add new public key to parser for signatures check
1304  * @param parser parser object
1305  * @param key PEM representation of a key
1306  * @param len length of the key
1307  * @param err if *err is NULL it is set to parser error
1308  * @return true if a key has been successfully added
1309  */
1310 UCL_EXTERN bool ucl_parser_pubkey_add(struct ucl_parser *parser,
1311 									  const unsigned char *key, size_t len);
1312 
1313 /**
1314  * Set FILENAME and CURDIR variables in parser
1315  * @param parser parser object
1316  * @param filename filename to set or NULL to set FILENAME to "undef" and CURDIR to getcwd()
1317  * @param need_expand perform realpath() if this variable is true and filename is not NULL
1318  * @return true if variables has been set
1319  */
1320 UCL_EXTERN bool ucl_parser_set_filevars(struct ucl_parser *parser, const char *filename,
1321 										bool need_expand);
1322 
1323 /**
1324  * Returns current file for the parser
1325  * @param parser parser object
1326  * @return current file or NULL if parsing memory
1327  */
1328 UCL_EXTERN const char *ucl_parser_get_cur_file(struct ucl_parser *parser);
1329 
1330 /**
1331  * Defines special handler for certain types of data (identified by magic)
1332  */
1333 typedef bool (*ucl_parser_special_handler_t)(struct ucl_parser *parser,
1334 											 const unsigned char *source, size_t source_len,
1335 											 unsigned char **destination, size_t *dest_len,
1336 											 void *user_data);
1337 
1338 /**
1339  * Special handler flags
1340  */
1341 enum ucl_special_handler_flags {
1342 	UCL_SPECIAL_HANDLER_DEFAULT = 0,
1343 	UCL_SPECIAL_HANDLER_PREPROCESS_ALL = (1u << 0),
1344 };
1345 
1346 /**
1347  * Special handler structure
1348  */
1349 struct ucl_parser_special_handler {
1350 	const unsigned char *magic;
1351 	size_t magic_len;
1352 	enum ucl_special_handler_flags flags;
1353 	ucl_parser_special_handler_t handler;
1354 	void (*free_function)(unsigned char *data, size_t len, void *user_data);
1355 	void *user_data;
1356 	struct ucl_parser_special_handler *next; /* Used internally */
1357 };
1358 
1359 /**
1360  * Add special handler for a parser, handles special sequences identified by magic
1361  * @param parser parser structure
1362  * @param handler handler structure
1363  */
1364 UCL_EXTERN void ucl_parser_add_special_handler(struct ucl_parser *parser,
1365 											   struct ucl_parser_special_handler *handler);
1366 
1367 /**
1368  * Handler for include traces:
1369  * @param parser parser object
1370  * @param parent where include is done from
1371  * @param args arguments to an include
1372  * @param path path of the include
1373  * @param pathlen length of the path
1374  * @param user_data opaque userdata
1375  */
1376 typedef void(ucl_include_trace_func_t)(struct ucl_parser *parser,
1377 									   const ucl_object_t *parent,
1378 									   const ucl_object_t *args,
1379 									   const char *path,
1380 									   size_t pathlen,
1381 									   void *user_data);
1382 
1383 /**
1384  * Register trace function for an include handler
1385  * @param parser parser object
1386  * @param func function to trace includes
1387  * @param user_data opaque data
1388  */
1389 UCL_EXTERN void ucl_parser_set_include_tracer(struct ucl_parser *parser,
1390 											  ucl_include_trace_func_t func,
1391 											  void *user_data);
1392 
1393 /** @} */
1394 
1395 /**
1396  * @defgroup emitter Emitting functions
1397  * These functions are used to serialise UCL objects to some string representation.
1398  *
1399  * @{
1400  */
1401 
1402 struct ucl_emitter_context;
1403 /**
1404  * Structure using for emitter callbacks
1405  */
1406 struct ucl_emitter_functions {
1407 	/** Append a single character */
1408 	int (*ucl_emitter_append_character)(unsigned char c, size_t nchars, void *ud);
1409 	/** Append a string of a specified length */
1410 	int (*ucl_emitter_append_len)(unsigned const char *str, size_t len, void *ud);
1411 	/** Append a 64 bit integer */
1412 	int (*ucl_emitter_append_int)(int64_t elt, void *ud);
1413 	/** Append floating point element */
1414 	int (*ucl_emitter_append_double)(double elt, void *ud);
1415 	/** Free userdata */
1416 	void (*ucl_emitter_free_func)(void *ud);
1417 	/** Opaque userdata pointer */
1418 	void *ud;
1419 };
1420 
1421 struct ucl_emitter_operations {
1422 	/** Write a primitive element */
1423 	void (*ucl_emitter_write_elt)(struct ucl_emitter_context *ctx,
1424 								  const ucl_object_t *obj, bool first, bool print_key);
1425 	/** Start ucl object */
1426 	void (*ucl_emitter_start_object)(struct ucl_emitter_context *ctx,
1427 									 const ucl_object_t *obj, bool first, bool print_key);
1428 	/** End ucl object */
1429 	void (*ucl_emitter_end_object)(struct ucl_emitter_context *ctx,
1430 								   const ucl_object_t *obj);
1431 	/** Start ucl array */
1432 	void (*ucl_emitter_start_array)(struct ucl_emitter_context *ctx,
1433 									const ucl_object_t *obj, bool first, bool print_key);
1434 	void (*ucl_emitter_end_array)(struct ucl_emitter_context *ctx,
1435 								  const ucl_object_t *obj);
1436 };
1437 
1438 /**
1439  * Structure that defines emitter functions
1440  */
1441 struct ucl_emitter_context {
1442 	/** Name of emitter (e.g. json, compact_json) */
1443 	const char *name;
1444 	/** Unique id (e.g. UCL_EMIT_JSON for standard emitters */
1445 	int id;
1446 	/** A set of output functions */
1447 	const struct ucl_emitter_functions *func;
1448 	/** A set of output operations */
1449 	const struct ucl_emitter_operations *ops;
1450 	/** Current amount of indent tabs */
1451 	unsigned int indent;
1452 	/** Top level object */
1453 	const ucl_object_t *top;
1454 	/** Optional comments */
1455 	const ucl_object_t *comments;
1456 };
1457 
1458 /**
1459  * Emit object to a string
1460  * @param obj object
1461  * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
1462  * #UCL_EMIT_CONFIG then emit config like object
1463  * @return dump of an object (must be freed after using) or NULL in case of error
1464  */
1465 UCL_EXTERN unsigned char *ucl_object_emit(const ucl_object_t *obj,
1466 										  enum ucl_emitter emit_type);
1467 
1468 /**
1469  * Emit object to a string that can contain `\0` inside
1470  * @param obj object
1471  * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
1472  * #UCL_EMIT_CONFIG then emit config like object
1473  * @param len the resulting length
1474  * @return dump of an object (must be freed after using) or NULL in case of error
1475  */
1476 UCL_EXTERN unsigned char *ucl_object_emit_len(const ucl_object_t *obj,
1477 											  enum ucl_emitter emit_type, size_t *len);
1478 
1479 /**
1480  * Emit object to a string
1481  * @param obj object
1482  * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is
1483  * #UCL_EMIT_CONFIG then emit config like object
1484  * @param emitter a set of emitter functions
1485  * @param comments optional comments for the parser
1486  * @return dump of an object (must be freed after using) or NULL in case of error
1487  */
1488 UCL_EXTERN bool ucl_object_emit_full(const ucl_object_t *obj,
1489 									 enum ucl_emitter emit_type,
1490 									 struct ucl_emitter_functions *emitter,
1491 									 const ucl_object_t *comments);
1492 
1493 /**
1494  * Start streamlined UCL object emitter
1495  * @param obj top UCL object
1496  * @param emit_type emit type
1497  * @param emitter a set of emitter functions
1498  * @return new streamlined context that should be freed by
1499  * `ucl_object_emit_streamline_finish`
1500  */
1501 UCL_EXTERN struct ucl_emitter_context *ucl_object_emit_streamline_new(
1502 	const ucl_object_t *obj, enum ucl_emitter emit_type,
1503 	struct ucl_emitter_functions *emitter);
1504 
1505 /**
1506  * Start object or array container for the streamlined output
1507  * @param ctx streamlined context
1508  * @param obj container object
1509  */
1510 UCL_EXTERN bool ucl_object_emit_streamline_start_container(
1511 	struct ucl_emitter_context *ctx, const ucl_object_t *obj);
1512 /**
1513  * Add a complete UCL object to streamlined output
1514  * @param ctx streamlined context
1515  * @param obj object to output
1516  */
1517 UCL_EXTERN void ucl_object_emit_streamline_add_object(
1518 	struct ucl_emitter_context *ctx, const ucl_object_t *obj);
1519 /**
1520  * End previously added container
1521  * @param ctx streamlined context
1522  */
1523 UCL_EXTERN void ucl_object_emit_streamline_end_container(
1524 	struct ucl_emitter_context *ctx);
1525 /**
1526  * Terminate streamlined container finishing all containers in it
1527  * @param ctx streamlined context
1528  */
1529 UCL_EXTERN void ucl_object_emit_streamline_finish(
1530 	struct ucl_emitter_context *ctx);
1531 
1532 /**
1533  * Returns functions to emit object to memory
1534  * @param pmem target pointer (should be freed by caller)
1535  * @return emitter functions structure
1536  */
1537 UCL_EXTERN struct ucl_emitter_functions *ucl_object_emit_memory_funcs(
1538 	void **pmem);
1539 
1540 /**
1541  * Returns functions to emit object to FILE *
1542  * @param fp FILE * object
1543  * @return emitter functions structure
1544  */
1545 UCL_EXTERN struct ucl_emitter_functions *ucl_object_emit_file_funcs(
1546 	FILE *fp);
1547 /**
1548  * Returns functions to emit object to a file descriptor
1549  * @param fd file descriptor
1550  * @return emitter functions structure
1551  */
1552 UCL_EXTERN struct ucl_emitter_functions *ucl_object_emit_fd_funcs(
1553 	int fd);
1554 
1555 /**
1556  * Free emitter functions
1557  * @param f pointer to functions
1558  */
1559 UCL_EXTERN void ucl_object_emit_funcs_free(struct ucl_emitter_functions *f);
1560 
1561 /** @} */
1562 
1563 /**
1564  * @defgroup schema Schema functions
1565  * These functions are used to validate UCL objects using json schema format
1566  *
1567  * @{
1568  */
1569 
1570 /**
1571  * Used to define UCL schema error
1572  */
1573 enum ucl_schema_error_code {
1574 	UCL_SCHEMA_OK = 0,               /**< no error */
1575 	UCL_SCHEMA_TYPE_MISMATCH,        /**< type of object is incorrect */
1576 	UCL_SCHEMA_INVALID_SCHEMA,       /**< schema is invalid */
1577 	UCL_SCHEMA_MISSING_PROPERTY,     /**< one or more missing properties */
1578 	UCL_SCHEMA_CONSTRAINT,           /**< constraint found */
1579 	UCL_SCHEMA_MISSING_DEPENDENCY,   /**< missing dependency */
1580 	UCL_SCHEMA_EXTERNAL_REF_MISSING, /**< cannot fetch external ref */
1581 	UCL_SCHEMA_EXTERNAL_REF_INVALID, /**< invalid external ref */
1582 	UCL_SCHEMA_INTERNAL_ERROR,       /**< something bad happened */
1583 	UCL_SCHEMA_UNKNOWN               /**< generic error */
1584 };
1585 
1586 /**
1587  * Generic ucl schema error
1588  */
1589 struct ucl_schema_error {
1590 	enum ucl_schema_error_code code; /**< error code */
1591 	char msg[128];                   /**< error message */
1592 	const ucl_object_t *obj;         /**< object where error occurred */
1593 };
1594 
1595 /**
1596  * Validate object `obj` using schema object `schema`.
1597  * @param schema schema object
1598  * @param obj object to validate
1599  * @param err error pointer, if this parameter is not NULL and error has been
1600  * occurred, then `err` is filled with the exact error definition.
1601  * @return true if `obj` is valid using `schema`
1602  */
1603 UCL_EXTERN bool ucl_object_validate(const ucl_object_t *schema,
1604 									const ucl_object_t *obj, struct ucl_schema_error *err);
1605 
1606 /**
1607  * Validate object `obj` using schema object `schema` and root schema at `root`.
1608  * @param schema schema object
1609  * @param obj object to validate
1610  * @param root root schema object
1611  * @param err error pointer, if this parameter is not NULL and error has been
1612  * occurred, then `err` is filled with the exact error definition.
1613  * @return true if `obj` is valid using `schema`
1614  */
1615 UCL_EXTERN bool ucl_object_validate_root(const ucl_object_t *schema,
1616 										 const ucl_object_t *obj,
1617 										 const ucl_object_t *root,
1618 										 struct ucl_schema_error *err);
1619 
1620 /**
1621  * Validate object `obj` using schema object `schema` and root schema at `root`
1622  * using some external references provided.
1623  * @param schema schema object
1624  * @param obj object to validate
1625  * @param root root schema object
1626  * @param ext_refs external references (might be modified during validation)
1627  * @param err error pointer, if this parameter is not NULL and error has been
1628  * occurred, then `err` is filled with the exact error definition.
1629  * @return true if `obj` is valid using `schema`
1630  */
1631 UCL_EXTERN bool ucl_object_validate_root_ext(const ucl_object_t *schema,
1632 											 const ucl_object_t *obj,
1633 											 const ucl_object_t *root,
1634 											 ucl_object_t *ext_refs,
1635 											 struct ucl_schema_error *err);
1636 
1637 /** @} */
1638 
1639 #ifdef __cplusplus
1640 }
1641 #endif
1642 /*
1643  * XXX: Poorly named API functions, need to replace them with the appropriate
1644  * named function. All API functions *must* use naming ucl_object_*. Usage of
1645  * ucl_obj* should be avoided.
1646  */
1647 #define ucl_obj_todouble_safe ucl_object_todouble_safe
1648 #define ucl_obj_todouble ucl_object_todouble
1649 #define ucl_obj_tostring ucl_object_tostring
1650 #define ucl_obj_tostring_safe ucl_object_tostring_safe
1651 #define ucl_obj_tolstring ucl_object_tolstring
1652 #define ucl_obj_tolstring_safe ucl_object_tolstring_safe
1653 #define ucl_obj_toint ucl_object_toint
1654 #define ucl_obj_toint_safe ucl_object_toint_safe
1655 #define ucl_obj_toboolean ucl_object_toboolean
1656 #define ucl_obj_toboolean_safe ucl_object_toboolean_safe
1657 #define ucl_obj_get_key ucl_object_find_key
1658 #define ucl_obj_get_keyl ucl_object_find_keyl
1659 #define ucl_obj_unref ucl_object_unref
1660 #define ucl_obj_ref ucl_object_ref
1661 #define ucl_obj_free ucl_object_free
1662 
1663 #define UCL_PRIORITY_MIN 0
1664 #define UCL_PRIORITY_MAX 15
1665 
1666 #endif /* UCL_H_ */
1667