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 35263019Sbapt#ifdef _WIN32 36263019Sbapt# define UCL_EXTERN __declspec(dllexport) 37263019Sbapt#else 38263019Sbapt# define UCL_EXTERN 39263019Sbapt#endif 40263019Sbapt 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 84268896Sbapt#ifdef __GNUC__ 85268896Sbapt#define UCL_DEPRECATED(func) func __attribute__ ((deprecated)) 86268896Sbapt#elif defined(_MSC_VER) 87268896Sbapt#define UCL_DEPRECATED(func) __declspec(deprecated) func 88268896Sbapt#else 89268896Sbapt#define UCL_DEPRECATED(func) func 90268896Sbapt#endif 91268896Sbapt 92262395Sbapt/** 93262395Sbapt * @defgroup structures Structures and types 94262395Sbapt * UCL defines several enumeration types used for error reporting or specifying flags and attributes. 95262395Sbapt * 96262395Sbapt * @{ 97262395Sbapt */ 98262395Sbapt 99262395Sbapt/** 100262395Sbapt * The common error codes returned by ucl parser 101262395Sbapt */ 102262395Sbapttypedef enum ucl_error { 103262395Sbapt UCL_EOK = 0, /**< No error */ 104262395Sbapt UCL_ESYNTAX, /**< Syntax error occurred during parsing */ 105262395Sbapt UCL_EIO, /**< IO error occurred during parsing */ 106262395Sbapt UCL_ESTATE, /**< Invalid state machine state */ 107262395Sbapt UCL_ENESTED, /**< Input has too many recursion levels */ 108262395Sbapt UCL_EMACRO, /**< Error processing a macro */ 109262395Sbapt UCL_EINTERNAL, /**< Internal unclassified error */ 110262395Sbapt UCL_ESSL /**< SSL error */ 111262395Sbapt} ucl_error_t; 112262395Sbapt 113262395Sbapt/** 114262395Sbapt * #ucl_object_t may have one of specified types, some types are compatible with each other and some are not. 115262395Sbapt * For example, you can always convert #UCL_TIME to #UCL_FLOAT. Also you can convert #UCL_FLOAT to #UCL_INTEGER 116262395Sbapt * by loosing floating point. Every object may be converted to a string by #ucl_object_tostring_forced() function. 117262395Sbapt * 118262395Sbapt */ 119262395Sbapttypedef enum ucl_type { 120262395Sbapt UCL_OBJECT = 0, /**< UCL object - key/value pairs */ 121262395Sbapt UCL_ARRAY, /**< UCL array */ 122262395Sbapt UCL_INT, /**< Integer number */ 123262395Sbapt UCL_FLOAT, /**< Floating point number */ 124262395Sbapt UCL_STRING, /**< Null terminated string */ 125262395Sbapt UCL_BOOLEAN, /**< Boolean value */ 126262395Sbapt UCL_TIME, /**< Time value (floating point number of seconds) */ 127262395Sbapt UCL_USERDATA, /**< Opaque userdata pointer (may be used in macros) */ 128262395Sbapt UCL_NULL /**< Null value */ 129262395Sbapt} ucl_type_t; 130262395Sbapt 131262395Sbapt/** 132262395Sbapt * You can use one of these types to serialise #ucl_object_t by using ucl_object_emit(). 133262395Sbapt */ 134262395Sbapttypedef enum ucl_emitter { 135262395Sbapt UCL_EMIT_JSON = 0, /**< Emit fine formatted JSON */ 136262395Sbapt UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */ 137262395Sbapt UCL_EMIT_CONFIG, /**< Emit human readable config format */ 138262395Sbapt UCL_EMIT_YAML /**< Emit embedded YAML format */ 139262395Sbapt} ucl_emitter_t; 140262395Sbapt 141262395Sbapt/** 142262395Sbapt * These flags defines parser behaviour. If you specify #UCL_PARSER_ZEROCOPY you must ensure 143262395Sbapt * that the input memory is not freed if an object is in use. Moreover, if you want to use 144262395Sbapt * zero-terminated keys and string values then you should not use zero-copy mode, as in this case 145262395Sbapt * UCL still has to perform copying implicitly. 146262395Sbapt */ 147262395Sbapttypedef enum ucl_parser_flags { 148262395Sbapt UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */ 149268896Sbapt UCL_PARSER_ZEROCOPY = 0x2, /**< Parse input in zero-copy mode if possible */ 150268896Sbapt UCL_PARSER_NO_TIME = 0x4 /**< Do not parse time and treat time values as strings */ 151262395Sbapt} ucl_parser_flags_t; 152262395Sbapt 153262395Sbapt/** 154262395Sbapt * String conversion flags, that are used in #ucl_object_fromstring_common function. 155262395Sbapt */ 156262395Sbapttypedef enum ucl_string_flags { 157262395Sbapt UCL_STRING_ESCAPE = 0x1, /**< Perform JSON escape */ 158262395Sbapt UCL_STRING_TRIM = 0x2, /**< Trim leading and trailing whitespaces */ 159262395Sbapt UCL_STRING_PARSE_BOOLEAN = 0x4, /**< Parse passed string and detect boolean */ 160262395Sbapt UCL_STRING_PARSE_INT = 0x8, /**< Parse passed string and detect integer number */ 161262395Sbapt UCL_STRING_PARSE_DOUBLE = 0x10, /**< Parse passed string and detect integer or float number */ 162268896Sbapt UCL_STRING_PARSE_TIME = 0x20, /**< Parse time strings */ 163268896Sbapt UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE|UCL_STRING_PARSE_TIME, /**< 164262395Sbapt Parse passed string and detect number */ 165262395Sbapt UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER, /**< 166262395Sbapt Parse passed string (and detect booleans and numbers) */ 167268896Sbapt UCL_STRING_PARSE_BYTES = 0x40 /**< Treat numbers as bytes */ 168262395Sbapt} ucl_string_flags_t; 169262395Sbapt 170262395Sbapt/** 171262395Sbapt * Basic flags for an object 172262395Sbapt */ 173262395Sbapttypedef enum ucl_object_flags { 174262395Sbapt UCL_OBJECT_ALLOCATED_KEY = 1, /**< An object has key allocated internally */ 175262395Sbapt UCL_OBJECT_ALLOCATED_VALUE = 2, /**< An object has a string value allocated internally */ 176262395Sbapt UCL_OBJECT_NEED_KEY_ESCAPE = 4 /**< The key of an object need to be escaped on output */ 177262395Sbapt} ucl_object_flags_t; 178262395Sbapt 179262395Sbapt/** 180262395Sbapt * UCL object structure. Please mention that the most of fields should not be touched by 181262395Sbapt * UCL users. In future, this structure may be converted to private one. 182262395Sbapt */ 183262395Sbapttypedef struct ucl_object_s { 184262395Sbapt /** 185262395Sbapt * Variant value type 186262395Sbapt */ 187262395Sbapt union { 188262395Sbapt int64_t iv; /**< Int value of an object */ 189262395Sbapt const char *sv; /**< String value of an object */ 190262395Sbapt double dv; /**< Double value of an object */ 191262395Sbapt struct ucl_object_s *av; /**< Array */ 192262395Sbapt void *ov; /**< Object */ 193262395Sbapt void* ud; /**< Opaque user data */ 194262395Sbapt } value; 195262395Sbapt const char *key; /**< Key of an object */ 196262395Sbapt struct ucl_object_s *next; /**< Array handle */ 197262395Sbapt struct ucl_object_s *prev; /**< Array handle */ 198262395Sbapt unsigned char* trash_stack[2]; /**< Pointer to allocated chunks */ 199262395Sbapt unsigned keylen; /**< Lenght of a key */ 200262395Sbapt unsigned len; /**< Size of an object */ 201262395Sbapt enum ucl_type type; /**< Real type */ 202262395Sbapt uint16_t ref; /**< Reference count */ 203262395Sbapt uint16_t flags; /**< Object flags */ 204262395Sbapt} ucl_object_t; 205262395Sbapt 206262395Sbapt/** @} */ 207262395Sbapt 208262395Sbapt/** 209262395Sbapt * @defgroup utils Utility functions 210262395Sbapt * A number of utility functions simplify handling of UCL objects 211262395Sbapt * 212262395Sbapt * @{ 213262395Sbapt */ 214262395Sbapt/** 215262395Sbapt * Copy and return a key of an object, returned key is zero-terminated 216262395Sbapt * @param obj CL object 217262395Sbapt * @return zero terminated key 218262395Sbapt */ 219268896SbaptUCL_EXTERN char* ucl_copy_key_trash (const ucl_object_t *obj); 220262395Sbapt 221262395Sbapt/** 222262395Sbapt * Copy and return a string value of an object, returned key is zero-terminated 223262395Sbapt * @param obj CL object 224262395Sbapt * @return zero terminated string representation of object value 225262395Sbapt */ 226268896SbaptUCL_EXTERN char* ucl_copy_value_trash (const ucl_object_t *obj); 227262395Sbapt 228262395Sbapt/** 229262395Sbapt * Creates a new object 230262395Sbapt * @return new object 231262395Sbapt */ 232268896SbaptUCL_EXTERN ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT; 233262395Sbapt 234262395Sbapt/** 235262395Sbapt * Create new object with type specified 236262395Sbapt * @param type type of a new object 237262395Sbapt * @return new object 238262395Sbapt */ 239268896SbaptUCL_EXTERN ucl_object_t* ucl_object_typed_new (ucl_type_t type) UCL_WARN_UNUSED_RESULT; 240262395Sbapt 241262395Sbapt/** 242268896Sbapt * Return the type of an object 243268896Sbapt * @return the object type 244268896Sbapt */ 245268896SbaptUCL_EXTERN ucl_type_t ucl_object_type (const ucl_object_t *obj); 246268896Sbapt 247268896Sbapt/** 248262395Sbapt * Convert any string to an ucl object making the specified transformations 249262395Sbapt * @param str fixed size or NULL terminated string 250262395Sbapt * @param len length (if len is zero, than str is treated as NULL terminated) 251262395Sbapt * @param flags conversion flags 252262395Sbapt * @return new object 253262395Sbapt */ 254263019SbaptUCL_EXTERN ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, 255262395Sbapt enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT; 256262395Sbapt 257262395Sbapt/** 258262395Sbapt * Create a UCL object from the specified string 259262395Sbapt * @param str NULL terminated string, will be json escaped 260262395Sbapt * @return new object 261262395Sbapt */ 262268896SbaptUCL_EXTERN ucl_object_t *ucl_object_fromstring (const char *str) UCL_WARN_UNUSED_RESULT; 263262395Sbapt 264262395Sbapt/** 265262395Sbapt * Create a UCL object from the specified string 266262395Sbapt * @param str fixed size string, will be json escaped 267262395Sbapt * @param len length of a string 268262395Sbapt * @return new object 269262395Sbapt */ 270268896SbaptUCL_EXTERN ucl_object_t *ucl_object_fromlstring (const char *str, 271268896Sbapt size_t len) UCL_WARN_UNUSED_RESULT; 272262395Sbapt 273262395Sbapt/** 274262395Sbapt * Create an object from an integer number 275262395Sbapt * @param iv number 276262395Sbapt * @return new object 277262395Sbapt */ 278268896SbaptUCL_EXTERN ucl_object_t* ucl_object_fromint (int64_t iv) UCL_WARN_UNUSED_RESULT; 279262395Sbapt 280262395Sbapt/** 281262395Sbapt * Create an object from a float number 282262395Sbapt * @param dv number 283262395Sbapt * @return new object 284262395Sbapt */ 285268896SbaptUCL_EXTERN ucl_object_t* ucl_object_fromdouble (double dv) UCL_WARN_UNUSED_RESULT; 286262395Sbapt 287262395Sbapt/** 288262395Sbapt * Create an object from a boolean 289262395Sbapt * @param bv bool value 290262395Sbapt * @return new object 291262395Sbapt */ 292268896SbaptUCL_EXTERN ucl_object_t* ucl_object_frombool (bool bv) UCL_WARN_UNUSED_RESULT; 293262395Sbapt 294262395Sbapt/** 295262395Sbapt * Insert a object 'elt' to the hash 'top' and associate it with key 'key' 296262395Sbapt * @param top destination object (will be created automatically if top is NULL) 297262395Sbapt * @param elt element to insert (must NOT be NULL) 298262395Sbapt * @param key key to associate with this object (either const or preallocated) 299262395Sbapt * @param keylen length of the key (or 0 for NULL terminated keys) 300262395Sbapt * @param copy_key make an internal copy of key 301268896Sbapt * @return true if key has been inserted 302262395Sbapt */ 303268896SbaptUCL_EXTERN bool ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, 304268896Sbapt const char *key, size_t keylen, bool copy_key); 305262395Sbapt 306262395Sbapt/** 307262395Sbapt * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed, 308262395Sbapt * if no object has been found this function works like ucl_object_insert_key() 309262395Sbapt * @param top destination object (will be created automatically if top is NULL) 310262395Sbapt * @param elt element to insert (must NOT be NULL) 311262395Sbapt * @param key key to associate with this object (either const or preallocated) 312262395Sbapt * @param keylen length of the key (or 0 for NULL terminated keys) 313262395Sbapt * @param copy_key make an internal copy of key 314268896Sbapt * @return true if key has been inserted 315262395Sbapt */ 316268896SbaptUCL_EXTERN bool ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, 317268896Sbapt const char *key, size_t keylen, bool copy_key); 318262395Sbapt 319262395Sbapt/** 320263019Sbapt * Delete a object associated with key 'key', old object will be unrefered, 321263019Sbapt * @param top object 322263019Sbapt * @param key key associated to the object to remove 323263019Sbapt * @param keylen length of the key (or 0 for NULL terminated keys) 324263019Sbapt */ 325268896SbaptUCL_EXTERN bool ucl_object_delete_keyl (ucl_object_t *top, 326268896Sbapt const char *key, size_t keylen); 327263019Sbapt 328263019Sbapt/** 329263019Sbapt * Delete a object associated with key 'key', old object will be unrefered, 330263019Sbapt * @param top object 331263019Sbapt * @param key key associated to the object to remove 332263019Sbapt */ 333268896SbaptUCL_EXTERN bool ucl_object_delete_key (ucl_object_t *top, 334268896Sbapt const char *key); 335263019Sbapt 336268896Sbapt 337263019Sbapt/** 338268896Sbapt * Delete key from `top` object returning the object deleted. This object is not 339268896Sbapt * released 340268896Sbapt * @param top object 341268896Sbapt * @param key key to remove 342268896Sbapt * @param keylen length of the key (or 0 for NULL terminated keys) 343268896Sbapt * @return removed object or NULL if object has not been found 344268896Sbapt */ 345268896SbaptUCL_EXTERN ucl_object_t* ucl_object_pop_keyl (ucl_object_t *top, const char *key, 346268896Sbapt size_t keylen) UCL_WARN_UNUSED_RESULT; 347268896Sbapt 348268896Sbapt/** 349268896Sbapt * Delete key from `top` object returning the object deleted. This object is not 350268896Sbapt * released 351268896Sbapt * @param top object 352268896Sbapt * @param key key to remove 353268896Sbapt * @return removed object or NULL if object has not been found 354268896Sbapt */ 355268896SbaptUCL_EXTERN ucl_object_t* ucl_object_pop_key (ucl_object_t *top, const char *key) 356268896Sbapt UCL_WARN_UNUSED_RESULT; 357268896Sbapt 358268896Sbapt/** 359262395Sbapt * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, 360262395Sbapt * try to merge its content 361262395Sbapt * @param top destination object (will be created automatically if top is NULL) 362262395Sbapt * @param elt element to insert (must NOT be NULL) 363262395Sbapt * @param key key to associate with this object (either const or preallocated) 364262395Sbapt * @param keylen length of the key (or 0 for NULL terminated keys) 365262395Sbapt * @param copy_key make an internal copy of key 366268896Sbapt * @return true if key has been inserted 367262395Sbapt */ 368268896SbaptUCL_EXTERN bool ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, 369268896Sbapt const char *key, size_t keylen, bool copy_key); 370262395Sbapt 371262395Sbapt/** 372262395Sbapt * Append an element to the front of array object 373262395Sbapt * @param top destination object (will be created automatically if top is NULL) 374262395Sbapt * @param elt element to append (must NOT be NULL) 375268896Sbapt * @return true if value has been inserted 376262395Sbapt */ 377268896SbaptUCL_EXTERN bool ucl_array_append (ucl_object_t *top, 378268896Sbapt ucl_object_t *elt); 379262395Sbapt 380262395Sbapt/** 381262395Sbapt * Append an element to the start of array object 382262395Sbapt * @param top destination object (will be created automatically if top is NULL) 383262395Sbapt * @param elt element to append (must NOT be NULL) 384268896Sbapt * @return true if value has been inserted 385262395Sbapt */ 386268896SbaptUCL_EXTERN bool ucl_array_prepend (ucl_object_t *top, 387268896Sbapt ucl_object_t *elt); 388262395Sbapt 389262395Sbapt/** 390262395Sbapt * Removes an element `elt` from the array `top`. Caller must unref the returned object when it is not 391262395Sbapt * needed. 392262395Sbapt * @param top array ucl object 393262395Sbapt * @param elt element to remove 394262395Sbapt * @return removed element or NULL if `top` is NULL or not an array 395262395Sbapt */ 396268896SbaptUCL_EXTERN ucl_object_t* ucl_array_delete (ucl_object_t *top, 397268896Sbapt ucl_object_t *elt); 398262395Sbapt 399262395Sbapt/** 400262395Sbapt * Returns the first element of the array `top` 401262395Sbapt * @param top array ucl object 402262395Sbapt * @return element or NULL if `top` is NULL or not an array 403262395Sbapt */ 404268896SbaptUCL_EXTERN const ucl_object_t* ucl_array_head (const ucl_object_t *top); 405262395Sbapt 406262395Sbapt/** 407262395Sbapt * Returns the last element of the array `top` 408262395Sbapt * @param top array ucl object 409262395Sbapt * @return element or NULL if `top` is NULL or not an array 410262395Sbapt */ 411268896SbaptUCL_EXTERN const ucl_object_t* ucl_array_tail (const ucl_object_t *top); 412262395Sbapt 413262395Sbapt/** 414262395Sbapt * Removes the last element from the array `top`. Caller must unref the returned object when it is not 415262395Sbapt * needed. 416262395Sbapt * @param top array ucl object 417262395Sbapt * @return removed element or NULL if `top` is NULL or not an array 418262395Sbapt */ 419268896SbaptUCL_EXTERN ucl_object_t* ucl_array_pop_last (ucl_object_t *top); 420262395Sbapt 421262395Sbapt/** 422268896Sbapt * Return object identified by an index of the array `top` 423268896Sbapt * @param obj object to get a key from (must be of type UCL_ARRAY) 424268896Sbapt * @param index index to return 425268896Sbapt * @return object at the specified index or NULL if index is not found 426268896Sbapt */ 427268896SbaptUCL_EXTERN const ucl_object_t* ucl_array_find_index (const ucl_object_t *top, 428268896Sbapt unsigned int index); 429268896Sbapt 430268896Sbapt/** 431262395Sbapt * Removes the first element from the array `top`. Caller must unref the returned object when it is not 432262395Sbapt * needed. 433262395Sbapt * @param top array ucl object 434262395Sbapt * @return removed element or NULL if `top` is NULL or not an array 435262395Sbapt */ 436268896SbaptUCL_EXTERN ucl_object_t* ucl_array_pop_first (ucl_object_t *top); 437262395Sbapt 438262395Sbapt/** 439262395Sbapt * Append a element to another element forming an implicit array 440262395Sbapt * @param head head to append (may be NULL) 441262395Sbapt * @param elt new element 442268896Sbapt * @return true if element has been inserted 443262395Sbapt */ 444268896SbaptUCL_EXTERN ucl_object_t * ucl_elt_append (ucl_object_t *head, 445268896Sbapt ucl_object_t *elt); 446262395Sbapt 447262395Sbapt/** 448262395Sbapt * Converts an object to double value 449262395Sbapt * @param obj CL object 450262395Sbapt * @param target target double variable 451262395Sbapt * @return true if conversion was successful 452262395Sbapt */ 453268896SbaptUCL_EXTERN bool ucl_object_todouble_safe (const ucl_object_t *obj, double *target); 454262395Sbapt 455262395Sbapt/** 456262395Sbapt * Unsafe version of \ref ucl_obj_todouble_safe 457262395Sbapt * @param obj CL object 458262395Sbapt * @return double value 459262395Sbapt */ 460268896SbaptUCL_EXTERN double ucl_object_todouble (const ucl_object_t *obj); 461262395Sbapt 462262395Sbapt/** 463262395Sbapt * Converts an object to integer value 464262395Sbapt * @param obj CL object 465262395Sbapt * @param target target integer variable 466262395Sbapt * @return true if conversion was successful 467262395Sbapt */ 468268896SbaptUCL_EXTERN bool ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target); 469262395Sbapt 470262395Sbapt/** 471262395Sbapt * Unsafe version of \ref ucl_obj_toint_safe 472262395Sbapt * @param obj CL object 473262395Sbapt * @return int value 474262395Sbapt */ 475268896SbaptUCL_EXTERN int64_t ucl_object_toint (const ucl_object_t *obj); 476262395Sbapt 477262395Sbapt/** 478262395Sbapt * Converts an object to boolean value 479262395Sbapt * @param obj CL object 480262395Sbapt * @param target target boolean variable 481262395Sbapt * @return true if conversion was successful 482262395Sbapt */ 483268896SbaptUCL_EXTERN bool ucl_object_toboolean_safe (const ucl_object_t *obj, bool *target); 484262395Sbapt 485262395Sbapt/** 486262395Sbapt * Unsafe version of \ref ucl_obj_toboolean_safe 487262395Sbapt * @param obj CL object 488262395Sbapt * @return boolean value 489262395Sbapt */ 490268896SbaptUCL_EXTERN bool ucl_object_toboolean (const ucl_object_t *obj); 491262395Sbapt 492262395Sbapt/** 493262395Sbapt * Converts an object to string value 494262395Sbapt * @param obj CL object 495262395Sbapt * @param target target string variable, no need to free value 496262395Sbapt * @return true if conversion was successful 497262395Sbapt */ 498268896SbaptUCL_EXTERN bool ucl_object_tostring_safe (const ucl_object_t *obj, const char **target); 499262395Sbapt 500262395Sbapt/** 501262395Sbapt * Unsafe version of \ref ucl_obj_tostring_safe 502262395Sbapt * @param obj CL object 503262395Sbapt * @return string value 504262395Sbapt */ 505268896SbaptUCL_EXTERN const char* ucl_object_tostring (const ucl_object_t *obj); 506262395Sbapt 507262395Sbapt/** 508262395Sbapt * Convert any object to a string in JSON notation if needed 509262395Sbapt * @param obj CL object 510262395Sbapt * @return string value 511262395Sbapt */ 512268896SbaptUCL_EXTERN const char* ucl_object_tostring_forced (const ucl_object_t *obj); 513262395Sbapt 514262395Sbapt/** 515262395Sbapt * Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it 516262395Sbapt * allows zero-copy (if #UCL_PARSER_ZEROCOPY has been used during parsing) 517262395Sbapt * @param obj CL object 518262395Sbapt * @param target target string variable, no need to free value 519262395Sbapt * @param tlen target length 520262395Sbapt * @return true if conversion was successful 521262395Sbapt */ 522268896SbaptUCL_EXTERN bool ucl_object_tolstring_safe (const ucl_object_t *obj, 523268896Sbapt const char **target, size_t *tlen); 524262395Sbapt 525262395Sbapt/** 526262395Sbapt * Unsafe version of \ref ucl_obj_tolstring_safe 527262395Sbapt * @param obj CL object 528262395Sbapt * @return string value 529262395Sbapt */ 530268896SbaptUCL_EXTERN const char* ucl_object_tolstring (const ucl_object_t *obj, size_t *tlen); 531262395Sbapt 532262395Sbapt/** 533262395Sbapt * Return object identified by a key in the specified object 534262395Sbapt * @param obj object to get a key from (must be of type UCL_OBJECT) 535262395Sbapt * @param key key to search 536262395Sbapt * @return object matched the specified key or NULL if key is not found 537262395Sbapt */ 538268896SbaptUCL_EXTERN const ucl_object_t* ucl_object_find_key (const ucl_object_t *obj, 539268896Sbapt const char *key); 540262395Sbapt 541262395Sbapt/** 542262395Sbapt * Return object identified by a fixed size key in the specified object 543262395Sbapt * @param obj object to get a key from (must be of type UCL_OBJECT) 544262395Sbapt * @param key key to search 545262395Sbapt * @param klen length of a key 546262395Sbapt * @return object matched the specified key or NULL if key is not found 547262395Sbapt */ 548268896SbaptUCL_EXTERN const ucl_object_t* ucl_object_find_keyl (const ucl_object_t *obj, 549268896Sbapt const char *key, size_t klen); 550262395Sbapt 551262395Sbapt/** 552268896Sbapt * Return object identified by dot notation string 553268896Sbapt * @param obj object to search in 554268896Sbapt * @param path dot.notation.path to the path to lookup. May use numeric .index on arrays 555268896Sbapt * @return object matched the specified path or NULL if path is not found 556268896Sbapt */ 557268896SbaptUCL_EXTERN const ucl_object_t *ucl_lookup_path (const ucl_object_t *obj, 558268896Sbapt const char *path); 559268896Sbapt 560268896Sbapt/** 561262395Sbapt * Returns a key of an object as a NULL terminated string 562262395Sbapt * @param obj CL object 563262395Sbapt * @return key or NULL if there is no key 564262395Sbapt */ 565268896SbaptUCL_EXTERN const char* ucl_object_key (const ucl_object_t *obj); 566262395Sbapt 567262395Sbapt/** 568262395Sbapt * Returns a key of an object as a fixed size string (may be more efficient) 569262395Sbapt * @param obj CL object 570262395Sbapt * @param len target key length 571262395Sbapt * @return key pointer 572262395Sbapt */ 573268896SbaptUCL_EXTERN const char* ucl_object_keyl (const ucl_object_t *obj, size_t *len); 574262395Sbapt 575262395Sbapt/** 576268896Sbapt * Increase reference count for an object 577268896Sbapt * @param obj object to ref 578262395Sbapt */ 579268896SbaptUCL_EXTERN ucl_object_t* ucl_object_ref (const ucl_object_t *obj); 580262395Sbapt 581262395Sbapt/** 582268896Sbapt * Free ucl object 583268896Sbapt * @param obj ucl object to free 584262395Sbapt */ 585268896SbaptUCL_DEPRECATED(UCL_EXTERN void ucl_object_free (ucl_object_t *obj)); 586262395Sbapt 587262395Sbapt/** 588262395Sbapt * Decrease reference count for an object 589262395Sbapt * @param obj object to unref 590262395Sbapt */ 591268896SbaptUCL_EXTERN void ucl_object_unref (ucl_object_t *obj); 592268896Sbapt 593262395Sbapt/** 594268896Sbapt * Compare objects `o1` and `o2` 595268896Sbapt * @param o1 the first object 596268896Sbapt * @param o2 the second object 597268896Sbapt * @return values >0, 0 and <0 if `o1` is more than, equal and less than `o2`. 598268896Sbapt * The order of comparison: 599268896Sbapt * 1) Type of objects 600268896Sbapt * 2) Size of objects 601268896Sbapt * 3) Content of objects 602268896Sbapt */ 603268896SbaptUCL_EXTERN int ucl_object_compare (const ucl_object_t *o1, 604268896Sbapt const ucl_object_t *o2); 605268896Sbapt 606268896Sbapt/** 607268896Sbapt * Sort UCL array using `cmp` compare function 608268896Sbapt * @param ar 609268896Sbapt * @param cmp 610268896Sbapt */ 611268896SbaptUCL_EXTERN void ucl_object_array_sort (ucl_object_t *ar, 612268896Sbapt int (*cmp)(const ucl_object_t *o1, const ucl_object_t *o2)); 613268896Sbapt 614268896Sbapt/** 615262395Sbapt * Opaque iterator object 616262395Sbapt */ 617262395Sbapttypedef void* ucl_object_iter_t; 618262395Sbapt 619262395Sbapt/** 620262395Sbapt * Get next key from an object 621262395Sbapt * @param obj object to iterate 622262395Sbapt * @param iter opaque iterator, must be set to NULL on the first call: 623262395Sbapt * ucl_object_iter_t it = NULL; 624262395Sbapt * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ... 625262395Sbapt * @return the next object or NULL 626262395Sbapt */ 627268896SbaptUCL_EXTERN const ucl_object_t* ucl_iterate_object (const ucl_object_t *obj, 628268896Sbapt ucl_object_iter_t *iter, bool expand_values); 629262395Sbapt/** @} */ 630262395Sbapt 631262395Sbapt 632262395Sbapt/** 633262395Sbapt * @defgroup parser Parsing functions 634262395Sbapt * These functions are used to parse UCL objects 635262395Sbapt * 636262395Sbapt * @{ 637262395Sbapt */ 638262395Sbapt 639262395Sbapt/** 640262395Sbapt * Macro handler for a parser 641262395Sbapt * @param data the content of macro 642262395Sbapt * @param len the length of content 643262395Sbapt * @param ud opaque user data 644262395Sbapt * @param err error pointer 645262395Sbapt * @return true if macro has been parsed 646262395Sbapt */ 647262395Sbapttypedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud); 648262395Sbapt 649262395Sbapt/* Opaque parser */ 650262395Sbaptstruct ucl_parser; 651262395Sbapt 652262395Sbapt/** 653262395Sbapt * Creates new parser object 654262395Sbapt * @param pool pool to allocate memory from 655262395Sbapt * @return new parser object 656262395Sbapt */ 657263019SbaptUCL_EXTERN struct ucl_parser* ucl_parser_new (int flags); 658262395Sbapt 659262395Sbapt/** 660262395Sbapt * Register new handler for a macro 661262395Sbapt * @param parser parser object 662262395Sbapt * @param macro macro name (without leading dot) 663262395Sbapt * @param handler handler (it is called immediately after macro is parsed) 664262395Sbapt * @param ud opaque user data for a handler 665262395Sbapt */ 666263019SbaptUCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, 667262395Sbapt ucl_macro_handler handler, void* ud); 668262395Sbapt 669262395Sbapt/** 670268896Sbapt * Handler to detect unregistered variables 671268896Sbapt * @param data variable data 672268896Sbapt * @param len length of variable 673268896Sbapt * @param replace (out) replace value for variable 674268896Sbapt * @param replace_len (out) replace length for variable 675268896Sbapt * @param need_free (out) UCL will free `dest` after usage 676268896Sbapt * @param ud opaque userdata 677268896Sbapt * @return true if variable 678268896Sbapt */ 679268896Sbapttypedef bool (*ucl_variable_handler) (const unsigned char *data, size_t len, 680268896Sbapt unsigned char **replace, size_t *replace_len, bool *need_free, void* ud); 681268896Sbapt 682268896Sbapt/** 683262395Sbapt * Register new parser variable 684262395Sbapt * @param parser parser object 685262395Sbapt * @param var variable name 686262395Sbapt * @param value variable value 687262395Sbapt */ 688263019SbaptUCL_EXTERN void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, 689262395Sbapt const char *value); 690262395Sbapt 691262395Sbapt/** 692268896Sbapt * Set handler for unknown variables 693268896Sbapt * @param parser parser structure 694268896Sbapt * @param handler desired handler 695268896Sbapt * @param ud opaque data for the handler 696268896Sbapt */ 697268896SbaptUCL_EXTERN void ucl_parser_set_variables_handler (struct ucl_parser *parser, 698268896Sbapt ucl_variable_handler handler, void *ud); 699268896Sbapt 700268896Sbapt/** 701262395Sbapt * Load new chunk to a parser 702262395Sbapt * @param parser parser structure 703262395Sbapt * @param data the pointer to the beginning of a chunk 704262395Sbapt * @param len the length of a chunk 705262395Sbapt * @param err if *err is NULL it is set to parser error 706262395Sbapt * @return true if chunk has been added and false in case of error 707262395Sbapt */ 708268896SbaptUCL_EXTERN bool ucl_parser_add_chunk (struct ucl_parser *parser, 709268896Sbapt const unsigned char *data, size_t len); 710262395Sbapt 711262395Sbapt/** 712268896Sbapt * Load ucl object from a string 713268896Sbapt * @param parser parser structure 714268896Sbapt * @param data the pointer to the string 715268896Sbapt * @param len the length of the string, if `len` is 0 then `data` must be zero-terminated string 716268896Sbapt * @return true if string has been added and false in case of error 717268896Sbapt */ 718268896SbaptUCL_EXTERN bool ucl_parser_add_string (struct ucl_parser *parser, 719268896Sbapt const char *data,size_t len); 720268896Sbapt 721268896Sbapt/** 722262395Sbapt * Load and add data from a file 723262395Sbapt * @param parser parser structure 724262395Sbapt * @param filename the name of file 725262395Sbapt * @param err if *err is NULL it is set to parser error 726262395Sbapt * @return true if chunk has been added and false in case of error 727262395Sbapt */ 728268896SbaptUCL_EXTERN bool ucl_parser_add_file (struct ucl_parser *parser, 729268896Sbapt const char *filename); 730262395Sbapt 731262395Sbapt/** 732268896Sbapt * Load and add data from a file descriptor 733262395Sbapt * @param parser parser structure 734268896Sbapt * @param filename the name of file 735262395Sbapt * @param err if *err is NULL it is set to parser error 736268896Sbapt * @return true if chunk has been added and false in case of error 737268896Sbapt */ 738268896SbaptUCL_EXTERN bool ucl_parser_add_fd (struct ucl_parser *parser, 739268896Sbapt int fd); 740268896Sbapt 741268896Sbapt/** 742268896Sbapt * Get a top object for a parser (refcount is increased) 743268896Sbapt * @param parser parser structure 744268896Sbapt * @param err if *err is NULL it is set to parser error 745262395Sbapt * @return top parser object or NULL 746262395Sbapt */ 747263019SbaptUCL_EXTERN ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); 748262395Sbapt 749262395Sbapt/** 750262395Sbapt * Get the error string if failing 751262395Sbapt * @param parser parser object 752262395Sbapt */ 753263019SbaptUCL_EXTERN const char *ucl_parser_get_error(struct ucl_parser *parser); 754262395Sbapt/** 755262395Sbapt * Free ucl parser object 756262395Sbapt * @param parser parser object 757262395Sbapt */ 758263019SbaptUCL_EXTERN void ucl_parser_free (struct ucl_parser *parser); 759262395Sbapt 760262395Sbapt/** 761262395Sbapt * Add new public key to parser for signatures check 762262395Sbapt * @param parser parser object 763262395Sbapt * @param key PEM representation of a key 764262395Sbapt * @param len length of the key 765262395Sbapt * @param err if *err is NULL it is set to parser error 766262395Sbapt * @return true if a key has been successfully added 767262395Sbapt */ 768263019SbaptUCL_EXTERN bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len); 769262395Sbapt 770262395Sbapt/** 771262395Sbapt * Set FILENAME and CURDIR variables in parser 772262395Sbapt * @param parser parser object 773262395Sbapt * @param filename filename to set or NULL to set FILENAME to "undef" and CURDIR to getcwd() 774262395Sbapt * @param need_expand perform realpath() if this variable is true and filename is not NULL 775262395Sbapt * @return true if variables has been set 776262395Sbapt */ 777263019SbaptUCL_EXTERN bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, 778262395Sbapt bool need_expand); 779262395Sbapt 780262395Sbapt/** @} */ 781262395Sbapt 782262395Sbapt/** 783262395Sbapt * @defgroup emitter Emitting functions 784262395Sbapt * These functions are used to serialise UCL objects to some string representation. 785262395Sbapt * 786262395Sbapt * @{ 787262395Sbapt */ 788262395Sbapt 789262395Sbapt/** 790262395Sbapt * Structure using for emitter callbacks 791262395Sbapt */ 792262395Sbaptstruct ucl_emitter_functions { 793262395Sbapt /** Append a single character */ 794262395Sbapt int (*ucl_emitter_append_character) (unsigned char c, size_t nchars, void *ud); 795262395Sbapt /** Append a string of a specified length */ 796262395Sbapt int (*ucl_emitter_append_len) (unsigned const char *str, size_t len, void *ud); 797262395Sbapt /** Append a 64 bit integer */ 798262395Sbapt int (*ucl_emitter_append_int) (int64_t elt, void *ud); 799262395Sbapt /** Append floating point element */ 800262395Sbapt int (*ucl_emitter_append_double) (double elt, void *ud); 801262395Sbapt /** Opaque userdata pointer */ 802262395Sbapt void *ud; 803262395Sbapt}; 804262395Sbapt 805262395Sbapt/** 806262395Sbapt * Emit object to a string 807262395Sbapt * @param obj object 808262395Sbapt * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is 809262395Sbapt * #UCL_EMIT_CONFIG then emit config like object 810262395Sbapt * @return dump of an object (must be freed after using) or NULL in case of error 811262395Sbapt */ 812268896SbaptUCL_EXTERN unsigned char *ucl_object_emit (const ucl_object_t *obj, 813268896Sbapt enum ucl_emitter emit_type); 814262395Sbapt 815262395Sbapt/** 816262395Sbapt * Emit object to a string 817262395Sbapt * @param obj object 818262395Sbapt * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is 819262395Sbapt * #UCL_EMIT_CONFIG then emit config like object 820262395Sbapt * @return dump of an object (must be freed after using) or NULL in case of error 821262395Sbapt */ 822268896SbaptUCL_EXTERN bool ucl_object_emit_full (const ucl_object_t *obj, 823268896Sbapt enum ucl_emitter emit_type, 824262395Sbapt struct ucl_emitter_functions *emitter); 825262395Sbapt/** @} */ 826262395Sbapt 827268896Sbapt/** 828268896Sbapt * @defgroup schema Schema functions 829268896Sbapt * These functions are used to validate UCL objects using json schema format 830268896Sbapt * 831268896Sbapt * @{ 832268896Sbapt */ 833268896Sbapt 834268896Sbapt/** 835268896Sbapt * Used to define UCL schema error 836268896Sbapt */ 837268896Sbaptenum ucl_schema_error_code { 838268896Sbapt UCL_SCHEMA_OK = 0, /**< no error */ 839268896Sbapt UCL_SCHEMA_TYPE_MISMATCH, /**< type of object is incorrect */ 840268896Sbapt UCL_SCHEMA_INVALID_SCHEMA, /**< schema is invalid */ 841268896Sbapt UCL_SCHEMA_MISSING_PROPERTY,/**< one or more missing properties */ 842268896Sbapt UCL_SCHEMA_CONSTRAINT, /**< constraint found */ 843268896Sbapt UCL_SCHEMA_MISSING_DEPENDENCY, /**< missing dependency */ 844268896Sbapt UCL_SCHEMA_UNKNOWN /**< generic error */ 845268896Sbapt}; 846268896Sbapt 847268896Sbapt/** 848268896Sbapt * Generic ucl schema error 849268896Sbapt */ 850268896Sbaptstruct ucl_schema_error { 851268896Sbapt enum ucl_schema_error_code code; /**< error code */ 852268896Sbapt char msg[128]; /**< error message */ 853268896Sbapt const ucl_object_t *obj; /**< object where error occured */ 854268896Sbapt}; 855268896Sbapt 856268896Sbapt/** 857268896Sbapt * Validate object `obj` using schema object `schema`. 858268896Sbapt * @param schema schema object 859268896Sbapt * @param obj object to validate 860268896Sbapt * @param err error pointer, if this parameter is not NULL and error has been 861268896Sbapt * occured, then `err` is filled with the exact error definition. 862268896Sbapt * @return true if `obj` is valid using `schema` 863268896Sbapt */ 864268896SbaptUCL_EXTERN bool ucl_object_validate (const ucl_object_t *schema, 865268896Sbapt const ucl_object_t *obj, struct ucl_schema_error *err); 866268896Sbapt 867268896Sbapt/** @} */ 868268896Sbapt 869262395Sbapt#ifdef __cplusplus 870262395Sbapt} 871262395Sbapt#endif 872262395Sbapt/* 873262395Sbapt * XXX: Poorly named API functions, need to replace them with the appropriate 874262395Sbapt * named function. All API functions *must* use naming ucl_object_*. Usage of 875262395Sbapt * ucl_obj* should be avoided. 876262395Sbapt */ 877262395Sbapt#define ucl_obj_todouble_safe ucl_object_todouble_safe 878262395Sbapt#define ucl_obj_todouble ucl_object_todouble 879262395Sbapt#define ucl_obj_tostring ucl_object_tostring 880262395Sbapt#define ucl_obj_tostring_safe ucl_object_tostring_safe 881262395Sbapt#define ucl_obj_tolstring ucl_object_tolstring 882262395Sbapt#define ucl_obj_tolstring_safe ucl_object_tolstring_safe 883262395Sbapt#define ucl_obj_toint ucl_object_toint 884262395Sbapt#define ucl_obj_toint_safe ucl_object_toint_safe 885262395Sbapt#define ucl_obj_toboolean ucl_object_toboolean 886262395Sbapt#define ucl_obj_toboolean_safe ucl_object_toboolean_safe 887262395Sbapt#define ucl_obj_get_key ucl_object_find_key 888262395Sbapt#define ucl_obj_get_keyl ucl_object_find_keyl 889262395Sbapt#define ucl_obj_unref ucl_object_unref 890262395Sbapt#define ucl_obj_ref ucl_object_ref 891262395Sbapt#define ucl_obj_free ucl_object_free 892262395Sbapt 893262395Sbapt#endif /* UCL_H_ */ 894