ucl.h revision 262395
1139747Simp/* Copyright (c) 2013, Vsevolod Stakhov 24Srgrimes * All rights reserved. 34Srgrimes * 44Srgrimes * Redistribution and use in source and binary forms, with or without 58876Srgrimes * modification, are permitted provided that the following conditions are met: 64Srgrimes * * Redistributions of source code must retain the above copyright 74Srgrimes * notice, this list of conditions and the following disclaimer. 84Srgrimes * * Redistributions in binary form must reproduce the above copyright 94Srgrimes * notice, this list of conditions and the following disclaimer in the 104Srgrimes * documentation and/or other materials provided with the distribution. 118876Srgrimes * 128876Srgrimes * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 134Srgrimes * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 144Srgrimes * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 158876Srgrimes * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 164Srgrimes * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 178876Srgrimes * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 184Srgrimes * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 194Srgrimes * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 204Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 214Srgrimes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 228876Srgrimes */ 234Srgrimes 244Srgrimes#ifndef UCL_H_ 254Srgrimes#define UCL_H_ 264Srgrimes 274Srgrimes#include <string.h> 284Srgrimes#include <stddef.h> 294Srgrimes#include <stdlib.h> 304Srgrimes#include <stdint.h> 314Srgrimes#include <stdbool.h> 324Srgrimes#include <stdarg.h> 334Srgrimes#include <stdio.h> 34116176Sobrien 35116176Sobrien/** 36116176Sobrien * @mainpage 37116176Sobrien * This is a reference manual for UCL API. You may find the description of UCL format by following this 382056Swollman * [github repository](https://github.com/vstakhov/libucl). 39131952Smarcel * 40145053Speter * This manual has several main sections: 4112734Sbde * - @ref structures 42131952Smarcel * - @ref utils 43131952Smarcel * - @ref parser 44131952Smarcel * - @ref emitter 4512662Sdg */ 4612734Sbde 472056Swollman/** 484Srgrimes * @file ucl.h 494Srgrimes * @brief UCL parsing and emitting functions 504Srgrimes * 5112720Sphk * UCL is universal configuration language, which is a form of 524Srgrimes * JSON with less strict rules that make it more comfortable for 534Srgrimes * using as a configuration language 544Srgrimes */ 554Srgrimes#ifdef __cplusplus 564Srgrimesextern "C" { 574Srgrimes#endif 584Srgrimes/* 594Srgrimes * Memory allocation utilities 6012720Sphk * UCL_ALLOC(size) - allocate memory for UCL 6112720Sphk * UCL_FREE(size, ptr) - free memory of specified size at ptr 6212720Sphk * Default: malloc and free 634Srgrimes */ 644Srgrimes#ifndef UCL_ALLOC 654Srgrimes#define UCL_ALLOC(size) malloc(size) 664Srgrimes#endif 674Srgrimes#ifndef UCL_FREE 684Srgrimes#define UCL_FREE(size, ptr) free(ptr) 69131952Smarcel#endif 704Srgrimes 714Srgrimes#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) 72131952Smarcel#define UCL_WARN_UNUSED_RESULT \ 734Srgrimes __attribute__((warn_unused_result)) 744Srgrimes#else 75137974Scognet#define UCL_WARN_UNUSED_RESULT 76137974Scognet#endif 77137974Scognet 78137974Scognet/** 79137974Scognet * @defgroup structures Structures and types 804Srgrimes * UCL defines several enumeration types used for error reporting or specifying flags and attributes. 814Srgrimes * 824Srgrimes * @{ 834Srgrimes */ 844Srgrimes 854Srgrimes/** 864Srgrimes * The common error codes returned by ucl parser 87137974Scognet */ 88137974Scognettypedef enum ucl_error { 89137974Scognet UCL_EOK = 0, /**< No error */ 90137974Scognet UCL_ESYNTAX, /**< Syntax error occurred during parsing */ 91137974Scognet UCL_EIO, /**< IO error occurred during parsing */ 92137974Scognet UCL_ESTATE, /**< Invalid state machine state */ 93137974Scognet UCL_ENESTED, /**< Input has too many recursion levels */ 94131952Smarcel UCL_EMACRO, /**< Error processing a macro */ 954Srgrimes UCL_EINTERNAL, /**< Internal unclassified error */ 964Srgrimes UCL_ESSL /**< SSL error */ 974Srgrimes} ucl_error_t; 984Srgrimes 994Srgrimes/** 1004Srgrimes * #ucl_object_t may have one of specified types, some types are compatible with each other and some are not. 1014Srgrimes * For example, you can always convert #UCL_TIME to #UCL_FLOAT. Also you can convert #UCL_FLOAT to #UCL_INTEGER 1024Srgrimes * by loosing floating point. Every object may be converted to a string by #ucl_object_tostring_forced() function. 1034Srgrimes * 1044Srgrimes */ 105131952Smarceltypedef enum ucl_type { 1064Srgrimes UCL_OBJECT = 0, /**< UCL object - key/value pairs */ 1074Srgrimes UCL_ARRAY, /**< UCL array */ 1084Srgrimes UCL_INT, /**< Integer number */ 1094Srgrimes UCL_FLOAT, /**< Floating point number */ 1104Srgrimes UCL_STRING, /**< Null terminated string */ 1114Srgrimes UCL_BOOLEAN, /**< Boolean value */ 1124Srgrimes UCL_TIME, /**< Time value (floating point number of seconds) */ 1134Srgrimes UCL_USERDATA, /**< Opaque userdata pointer (may be used in macros) */ 1144Srgrimes UCL_NULL /**< Null value */ 1154Srgrimes} ucl_type_t; 1164Srgrimes 1174Srgrimes/** 1184Srgrimes * You can use one of these types to serialise #ucl_object_t by using ucl_object_emit(). 1194Srgrimes */ 12083506Sdfrtypedef enum ucl_emitter { 12183506Sdfr UCL_EMIT_JSON = 0, /**< Emit fine formatted JSON */ 12236735Sdfr UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */ 1234Srgrimes UCL_EMIT_CONFIG, /**< Emit human readable config format */ 1248876Srgrimes UCL_EMIT_YAML /**< Emit embedded YAML format */ 1254Srgrimes} ucl_emitter_t; 1264Srgrimes 1274Srgrimes/** 1284Srgrimes * These flags defines parser behaviour. If you specify #UCL_PARSER_ZEROCOPY you must ensure 1294Srgrimes * that the input memory is not freed if an object is in use. Moreover, if you want to use 1304Srgrimes * zero-terminated keys and string values then you should not use zero-copy mode, as in this case 1314Srgrimes * UCL still has to perform copying implicitly. 1324Srgrimes */ 1334Srgrimestypedef enum ucl_parser_flags { 1344Srgrimes UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */ 1354Srgrimes UCL_PARSER_ZEROCOPY = 0x2 /**< Parse input in zero-copy mode if possible */ 1364Srgrimes} ucl_parser_flags_t; 1374Srgrimes 1384Srgrimes/** 1394Srgrimes * String conversion flags, that are used in #ucl_object_fromstring_common function. 1404Srgrimes */ 1414Srgrimestypedef enum ucl_string_flags { 1424Srgrimes UCL_STRING_ESCAPE = 0x1, /**< Perform JSON escape */ 1434Srgrimes UCL_STRING_TRIM = 0x2, /**< Trim leading and trailing whitespaces */ 1444Srgrimes UCL_STRING_PARSE_BOOLEAN = 0x4, /**< Parse passed string and detect boolean */ 1454Srgrimes UCL_STRING_PARSE_INT = 0x8, /**< Parse passed string and detect integer number */ 14698694Smux UCL_STRING_PARSE_DOUBLE = 0x10, /**< Parse passed string and detect integer or float number */ 1474Srgrimes UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE , /**< 14898694Smux Parse passed string and detect number */ 1494Srgrimes UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER, /**< 1504Srgrimes Parse passed string (and detect booleans and numbers) */ 1514Srgrimes UCL_STRING_PARSE_BYTES = 0x20 /**< Treat numbers as bytes */ 1524Srgrimes} ucl_string_flags_t; 1534Srgrimes 1544Srgrimes/** 1554Srgrimes * Basic flags for an object 1564Srgrimes */ 1574Srgrimestypedef enum ucl_object_flags { 1584Srgrimes UCL_OBJECT_ALLOCATED_KEY = 1, /**< An object has key allocated internally */ 1594Srgrimes UCL_OBJECT_ALLOCATED_VALUE = 2, /**< An object has a string value allocated internally */ 1604Srgrimes UCL_OBJECT_NEED_KEY_ESCAPE = 4 /**< The key of an object need to be escaped on output */ 1614Srgrimes} ucl_object_flags_t; 1624Srgrimes 1634Srgrimes/** 1644Srgrimes * UCL object structure. Please mention that the most of fields should not be touched by 1654Srgrimes * UCL users. In future, this structure may be converted to private one. 1664Srgrimes */ 1674Srgrimestypedef struct ucl_object_s { 1684Srgrimes /** 16998694Smux * Variant value type 1704Srgrimes */ 17198694Smux union { 1724Srgrimes int64_t iv; /**< Int value of an object */ 1734Srgrimes const char *sv; /**< String value of an object */ 1744Srgrimes double dv; /**< Double value of an object */ 1754Srgrimes struct ucl_object_s *av; /**< Array */ 1764Srgrimes void *ov; /**< Object */ 1774Srgrimes void* ud; /**< Opaque user data */ 1784Srgrimes } value; 1794Srgrimes const char *key; /**< Key of an object */ 1804Srgrimes struct ucl_object_s *next; /**< Array handle */ 1814Srgrimes struct ucl_object_s *prev; /**< Array handle */ 1824Srgrimes unsigned char* trash_stack[2]; /**< Pointer to allocated chunks */ 1834Srgrimes unsigned keylen; /**< Lenght of a key */ 1844Srgrimes unsigned len; /**< Size of an object */ 1854Srgrimes enum ucl_type type; /**< Real type */ 186131952Smarcel uint16_t ref; /**< Reference count */ 1874Srgrimes uint16_t flags; /**< Object flags */ 1884Srgrimes} ucl_object_t; 1894Srgrimes 1904Srgrimes/** @} */ 1914Srgrimes 1924Srgrimes/** 1934Srgrimes * @defgroup utils Utility functions 1944Srgrimes * A number of utility functions simplify handling of UCL objects 1954Srgrimes * 1964Srgrimes * @{ 1974Srgrimes */ 1984Srgrimes/** 1994Srgrimes * Copy and return a key of an object, returned key is zero-terminated 2004Srgrimes * @param obj CL object 2014Srgrimes * @return zero terminated key 2024Srgrimes */ 2034Srgrimeschar* ucl_copy_key_trash (ucl_object_t *obj); 2044Srgrimes 2054Srgrimes/** 2064Srgrimes * Copy and return a string value of an object, returned key is zero-terminated 2074Srgrimes * @param obj CL object 2084Srgrimes * @return zero terminated string representation of object value 2094Srgrimes */ 2104Srgrimeschar* ucl_copy_value_trash (ucl_object_t *obj); 21181670Sobrien 2124Srgrimes/** 2134Srgrimes * Creates a new object 2144Srgrimes * @return new object 2154Srgrimes */ 2164Srgrimesstatic inline ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT; 2174Srgrimesstatic inline ucl_object_t * 2184Srgrimesucl_object_new (void) 2194Srgrimes{ 220131952Smarcel ucl_object_t *new; 2214Srgrimes new = malloc (sizeof (ucl_object_t)); 2224Srgrimes if (new != NULL) { 2234Srgrimes memset (new, 0, sizeof (ucl_object_t)); 2244Srgrimes new->ref = 1; 2254Srgrimes new->type = UCL_NULL; 226131952Smarcel } 2274Srgrimes return new; 2284Srgrimes} 2294Srgrimes 2304Srgrimes/** 2314Srgrimes * Create new object with type specified 2324Srgrimes * @param type type of a new object 2334Srgrimes * @return new object 2344Srgrimes */ 2354Srgrimesstatic inline ucl_object_t* ucl_object_typed_new (unsigned int type) UCL_WARN_UNUSED_RESULT; 2364Srgrimesstatic inline ucl_object_t * 2374Srgrimesucl_object_typed_new (unsigned int type) 2384Srgrimes{ 2394Srgrimes ucl_object_t *new; 2404Srgrimes new = malloc (sizeof (ucl_object_t)); 2414Srgrimes if (new != NULL) { 2424Srgrimes memset (new, 0, sizeof (ucl_object_t)); 2434Srgrimes new->ref = 1; 2444Srgrimes new->type = (type <= UCL_NULL ? type : UCL_NULL); 2454Srgrimes } 2464Srgrimes return new; 2478876Srgrimes} 2484Srgrimes 2494Srgrimes/** 2504Srgrimes * Convert any string to an ucl object making the specified transformations 2514Srgrimes * @param str fixed size or NULL terminated string 2524Srgrimes * @param len length (if len is zero, than str is treated as NULL terminated) 2534Srgrimes * @param flags conversion flags 2544Srgrimes * @return new object 2554Srgrimes */ 2564Srgrimesucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, 2574Srgrimes enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT; 2584Srgrimes 2598876Srgrimes/** 2604Srgrimes * Create a UCL object from the specified string 2614Srgrimes * @param str NULL terminated string, will be json escaped 262131952Smarcel * @return new object 2634Srgrimes */ 264131952Smarcelstatic inline ucl_object_t * 265131952Smarcelucl_object_fromstring (const char *str) 2664Srgrimes{ 2674Srgrimes return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE); 2684Srgrimes} 2694Srgrimes 2704Srgrimes/** 2714Srgrimes * Create a UCL object from the specified string 272181175Scognet * @param str fixed size string, will be json escaped 273131952Smarcel * @param len length of a string 274131952Smarcel * @return new object 275131952Smarcel */ 276131952Smarcelstatic inline ucl_object_t * 277131952Smarcelucl_object_fromlstring (const char *str, size_t len) 2784Srgrimes{ 279131952Smarcel return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE); 2804Srgrimes} 2814Srgrimes 2824Srgrimes/** 2834Srgrimes * Create an object from an integer number 284131952Smarcel * @param iv number 2854Srgrimes * @return new object 2864Srgrimes */ 28737392Sdfrstatic inline ucl_object_t * 288131952Smarcelucl_object_fromint (int64_t iv) 289131952Smarcel{ 29037392Sdfr ucl_object_t *obj; 2914Srgrimes 292131952Smarcel obj = ucl_object_new (); 293131952Smarcel if (obj != NULL) { 2944Srgrimes obj->type = UCL_INT; 2954Srgrimes obj->value.iv = iv; 2964Srgrimes } 29781670Sobrien 2984Srgrimes return obj; 2994Srgrimes} 3004Srgrimes 3014Srgrimes/** 3024Srgrimes * Create an object from a float number 3034Srgrimes * @param dv number 3044Srgrimes * @return new object 3054Srgrimes */ 30612473Sbdestatic inline ucl_object_t * 3074Srgrimesucl_object_fromdouble (double dv) 3084Srgrimes{ 3094Srgrimes ucl_object_t *obj; 3104Srgrimes 3114Srgrimes obj = ucl_object_new (); 3124Srgrimes if (obj != NULL) { 3134Srgrimes obj->type = UCL_FLOAT; 3144Srgrimes obj->value.dv = dv; 3154Srgrimes } 3164Srgrimes 3174Srgrimes return obj; 3184Srgrimes} 3194Srgrimes 3204Srgrimes/** 3214Srgrimes * Create an object from a boolean 3224Srgrimes * @param bv bool value 3234Srgrimes * @return new object 3244Srgrimes */ 3254Srgrimesstatic inline ucl_object_t * 3264Srgrimesucl_object_frombool (bool bv) 3274Srgrimes{ 3284Srgrimes ucl_object_t *obj; 3294Srgrimes 3304Srgrimes obj = ucl_object_new (); 3314Srgrimes if (obj != NULL) { 3324Srgrimes obj->type = UCL_BOOLEAN; 33312473Sbde obj->value.iv = bv; 3344Srgrimes } 3354Srgrimes 3364Srgrimes return obj; 3374Srgrimes} 3384Srgrimes 3394Srgrimes/** 3404Srgrimes * Insert a object 'elt' to the hash 'top' and associate it with key 'key' 3414Srgrimes * @param top destination object (will be created automatically if top is NULL) 3424Srgrimes * @param elt element to insert (must NOT be NULL) 3434Srgrimes * @param key key to associate with this object (either const or preallocated) 3444Srgrimes * @param keylen length of the key (or 0 for NULL terminated keys) 3454Srgrimes * @param copy_key make an internal copy of key 3464Srgrimes * @return new value of top object 3474Srgrimes */ 3484Srgrimesucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, 3494Srgrimes const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 3504Srgrimes 3514Srgrimes/** 3524Srgrimes * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed, 3534Srgrimes * if no object has been found this function works like ucl_object_insert_key() 3544Srgrimes * @param top destination object (will be created automatically if top is NULL) 35512473Sbde * @param elt element to insert (must NOT be NULL) 3564Srgrimes * @param key key to associate with this object (either const or preallocated) 3574Srgrimes * @param keylen length of the key (or 0 for NULL terminated keys) 3584Srgrimes * @param copy_key make an internal copy of key 3594Srgrimes * @return new value of top object 3604Srgrimes */ 3614Srgrimesucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, 3624Srgrimes const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 3634Srgrimes 3644Srgrimes/** 3654Srgrimes * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, 3664Srgrimes * try to merge its content 3674Srgrimes * @param top destination object (will be created automatically if top is NULL) 3684Srgrimes * @param elt element to insert (must NOT be NULL) 3694Srgrimes * @param key key to associate with this object (either const or preallocated) 3704Srgrimes * @param keylen length of the key (or 0 for NULL terminated keys) 3714Srgrimes * @param copy_key make an internal copy of key 3724Srgrimes * @return new value of top object 3734Srgrimes */ 3744Srgrimesucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, 3754Srgrimes const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 3764Srgrimes 3774Srgrimes/** 3784Srgrimes * Append an element to the front of array object 37912473Sbde * @param top destination object (will be created automatically if top is NULL) 3804Srgrimes * @param elt element to append (must NOT be NULL) 3814Srgrimes * @return new value of top object 3824Srgrimes */ 3834Srgrimesstatic inline ucl_object_t * ucl_array_append (ucl_object_t *top, 3844Srgrimes ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; 3854Srgrimesstatic inline ucl_object_t * 3864Srgrimesucl_array_append (ucl_object_t *top, ucl_object_t *elt) 3874Srgrimes{ 3884Srgrimes ucl_object_t *head; 3894Srgrimes 3904Srgrimes if (elt == NULL) { 3914Srgrimes return NULL; 3924Srgrimes } 393 394 if (top == NULL) { 395 top = ucl_object_typed_new (UCL_ARRAY); 396 top->value.av = elt; 397 elt->next = NULL; 398 elt->prev = elt; 399 top->len = 1; 400 } 401 else { 402 head = top->value.av; 403 if (head == NULL) { 404 top->value.av = elt; 405 elt->prev = elt; 406 } 407 else { 408 elt->prev = head->prev; 409 head->prev->next = elt; 410 head->prev = elt; 411 } 412 elt->next = NULL; 413 top->len ++; 414 } 415 416 return top; 417} 418 419/** 420 * Append an element to the start of array object 421 * @param top destination object (will be created automatically if top is NULL) 422 * @param elt element to append (must NOT be NULL) 423 * @return new value of top object 424 */ 425static inline ucl_object_t * ucl_array_prepend (ucl_object_t *top, 426 ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; 427static inline ucl_object_t * 428ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt) 429{ 430 ucl_object_t *head; 431 432 if (elt == NULL) { 433 return NULL; 434 } 435 436 if (top == NULL) { 437 top = ucl_object_typed_new (UCL_ARRAY); 438 top->value.av = elt; 439 elt->next = NULL; 440 elt->prev = elt; 441 top->len = 1; 442 } 443 else { 444 head = top->value.av; 445 if (head == NULL) { 446 top->value.av = elt; 447 elt->prev = elt; 448 } 449 else { 450 elt->prev = head->prev; 451 head->prev = elt; 452 } 453 elt->next = head; 454 top->value.av = elt; 455 top->len ++; 456 } 457 458 return top; 459} 460 461/** 462 * Removes an element `elt` from the array `top`. Caller must unref the returned object when it is not 463 * needed. 464 * @param top array ucl object 465 * @param elt element to remove 466 * @return removed element or NULL if `top` is NULL or not an array 467 */ 468static inline ucl_object_t * 469ucl_array_delete (ucl_object_t *top, ucl_object_t *elt) 470{ 471 ucl_object_t *head; 472 473 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 474 return NULL; 475 } 476 head = top->value.av; 477 478 if (elt->prev == elt) { 479 top->value.av = NULL; 480 } 481 else if (elt == head) { 482 elt->next->prev = elt->prev; 483 top->value.av = elt->next; 484 } 485 else { 486 elt->prev->next = elt->next; 487 if (elt->next) { 488 elt->next->prev = elt->prev; 489 } 490 else { 491 head->prev = elt->prev; 492 } 493 } 494 elt->next = NULL; 495 elt->prev = elt; 496 top->len --; 497 498 return elt; 499} 500 501/** 502 * Returns the first element of the array `top` 503 * @param top array ucl object 504 * @return element or NULL if `top` is NULL or not an array 505 */ 506static inline ucl_object_t * 507ucl_array_head (ucl_object_t *top) 508{ 509 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 510 return NULL; 511 } 512 return top->value.av; 513} 514 515/** 516 * Returns the last element of the array `top` 517 * @param top array ucl object 518 * @return element or NULL if `top` is NULL or not an array 519 */ 520static inline ucl_object_t * 521ucl_array_tail (ucl_object_t *top) 522{ 523 if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 524 return NULL; 525 } 526 return top->value.av->prev; 527} 528 529/** 530 * Removes the last element from the array `top`. Caller must unref the returned object when it is not 531 * needed. 532 * @param top array ucl object 533 * @return removed element or NULL if `top` is NULL or not an array 534 */ 535static inline ucl_object_t * 536ucl_array_pop_last (ucl_object_t *top) 537{ 538 return ucl_array_delete (top, ucl_array_tail (top)); 539} 540 541/** 542 * Removes the first element from the array `top`. Caller must unref the returned object when it is not 543 * needed. 544 * @param top array ucl object 545 * @return removed element or NULL if `top` is NULL or not an array 546 */ 547static inline ucl_object_t * 548ucl_array_pop_first (ucl_object_t *top) 549{ 550 return ucl_array_delete (top, ucl_array_head (top)); 551} 552 553/** 554 * Append a element to another element forming an implicit array 555 * @param head head to append (may be NULL) 556 * @param elt new element 557 * @return new head if applicable 558 */ 559static inline ucl_object_t * ucl_elt_append (ucl_object_t *head, 560 ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; 561static inline ucl_object_t * 562ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) 563{ 564 565 if (head == NULL) { 566 elt->next = NULL; 567 elt->prev = elt; 568 head = elt; 569 } 570 else { 571 elt->prev = head->prev; 572 head->prev->next = elt; 573 head->prev = elt; 574 elt->next = NULL; 575 } 576 577 return head; 578} 579 580/** 581 * Converts an object to double value 582 * @param obj CL object 583 * @param target target double variable 584 * @return true if conversion was successful 585 */ 586static inline bool 587ucl_object_todouble_safe (ucl_object_t *obj, double *target) 588{ 589 if (obj == NULL) { 590 return false; 591 } 592 switch (obj->type) { 593 case UCL_INT: 594 *target = obj->value.iv; /* Probaly could cause overflow */ 595 break; 596 case UCL_FLOAT: 597 case UCL_TIME: 598 *target = obj->value.dv; 599 break; 600 default: 601 return false; 602 } 603 604 return true; 605} 606 607/** 608 * Unsafe version of \ref ucl_obj_todouble_safe 609 * @param obj CL object 610 * @return double value 611 */ 612static inline double 613ucl_object_todouble (ucl_object_t *obj) 614{ 615 double result = 0.; 616 617 ucl_object_todouble_safe (obj, &result); 618 return result; 619} 620 621/** 622 * Converts an object to integer value 623 * @param obj CL object 624 * @param target target integer variable 625 * @return true if conversion was successful 626 */ 627static inline bool 628ucl_object_toint_safe (ucl_object_t *obj, int64_t *target) 629{ 630 if (obj == NULL) { 631 return false; 632 } 633 switch (obj->type) { 634 case UCL_INT: 635 *target = obj->value.iv; 636 break; 637 case UCL_FLOAT: 638 case UCL_TIME: 639 *target = obj->value.dv; /* Loosing of decimal points */ 640 break; 641 default: 642 return false; 643 } 644 645 return true; 646} 647 648/** 649 * Unsafe version of \ref ucl_obj_toint_safe 650 * @param obj CL object 651 * @return int value 652 */ 653static inline int64_t 654ucl_object_toint (ucl_object_t *obj) 655{ 656 int64_t result = 0; 657 658 ucl_object_toint_safe (obj, &result); 659 return result; 660} 661 662/** 663 * Converts an object to boolean value 664 * @param obj CL object 665 * @param target target boolean variable 666 * @return true if conversion was successful 667 */ 668static inline bool 669ucl_object_toboolean_safe (ucl_object_t *obj, bool *target) 670{ 671 if (obj == NULL) { 672 return false; 673 } 674 switch (obj->type) { 675 case UCL_BOOLEAN: 676 *target = (obj->value.iv == true); 677 break; 678 default: 679 return false; 680 } 681 682 return true; 683} 684 685/** 686 * Unsafe version of \ref ucl_obj_toboolean_safe 687 * @param obj CL object 688 * @return boolean value 689 */ 690static inline bool 691ucl_object_toboolean (ucl_object_t *obj) 692{ 693 bool result = false; 694 695 ucl_object_toboolean_safe (obj, &result); 696 return result; 697} 698 699/** 700 * Converts an object to string value 701 * @param obj CL object 702 * @param target target string variable, no need to free value 703 * @return true if conversion was successful 704 */ 705static inline bool 706ucl_object_tostring_safe (ucl_object_t *obj, const char **target) 707{ 708 if (obj == NULL) { 709 return false; 710 } 711 712 switch (obj->type) { 713 case UCL_STRING: 714 *target = ucl_copy_value_trash (obj); 715 break; 716 default: 717 return false; 718 } 719 720 return true; 721} 722 723/** 724 * Unsafe version of \ref ucl_obj_tostring_safe 725 * @param obj CL object 726 * @return string value 727 */ 728static inline const char * 729ucl_object_tostring (ucl_object_t *obj) 730{ 731 const char *result = NULL; 732 733 ucl_object_tostring_safe (obj, &result); 734 return result; 735} 736 737/** 738 * Convert any object to a string in JSON notation if needed 739 * @param obj CL object 740 * @return string value 741 */ 742static inline const char * 743ucl_object_tostring_forced (ucl_object_t *obj) 744{ 745 return ucl_copy_value_trash (obj); 746} 747 748/** 749 * Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it 750 * allows zero-copy (if #UCL_PARSER_ZEROCOPY has been used during parsing) 751 * @param obj CL object 752 * @param target target string variable, no need to free value 753 * @param tlen target length 754 * @return true if conversion was successful 755 */ 756static inline bool 757ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen) 758{ 759 if (obj == NULL) { 760 return false; 761 } 762 switch (obj->type) { 763 case UCL_STRING: 764 *target = obj->value.sv; 765 *tlen = obj->len; 766 break; 767 default: 768 return false; 769 } 770 771 return true; 772} 773 774/** 775 * Unsafe version of \ref ucl_obj_tolstring_safe 776 * @param obj CL object 777 * @return string value 778 */ 779static inline const char * 780ucl_object_tolstring (ucl_object_t *obj, size_t *tlen) 781{ 782 const char *result = NULL; 783 784 ucl_object_tolstring_safe (obj, &result, tlen); 785 return result; 786} 787 788/** 789 * Return object identified by a key in the specified object 790 * @param obj object to get a key from (must be of type UCL_OBJECT) 791 * @param key key to search 792 * @return object matched the specified key or NULL if key is not found 793 */ 794ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key); 795 796/** 797 * Return object identified by a fixed size key in the specified object 798 * @param obj object to get a key from (must be of type UCL_OBJECT) 799 * @param key key to search 800 * @param klen length of a key 801 * @return object matched the specified key or NULL if key is not found 802 */ 803ucl_object_t *ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen); 804 805/** 806 * Returns a key of an object as a NULL terminated string 807 * @param obj CL object 808 * @return key or NULL if there is no key 809 */ 810static inline const char * 811ucl_object_key (ucl_object_t *obj) 812{ 813 return ucl_copy_key_trash (obj); 814} 815 816/** 817 * Returns a key of an object as a fixed size string (may be more efficient) 818 * @param obj CL object 819 * @param len target key length 820 * @return key pointer 821 */ 822static inline const char * 823ucl_object_keyl (ucl_object_t *obj, size_t *len) 824{ 825 *len = obj->keylen; 826 return obj->key; 827} 828 829/** 830 * Free ucl object 831 * @param obj ucl object to free 832 */ 833void ucl_object_free (ucl_object_t *obj); 834 835/** 836 * Increase reference count for an object 837 * @param obj object to ref 838 */ 839static inline ucl_object_t * 840ucl_object_ref (ucl_object_t *obj) { 841 obj->ref ++; 842 return obj; 843} 844 845/** 846 * Decrease reference count for an object 847 * @param obj object to unref 848 */ 849static inline void 850ucl_object_unref (ucl_object_t *obj) { 851 if (obj != NULL && --obj->ref <= 0) { 852 ucl_object_free (obj); 853 } 854} 855/** 856 * Opaque iterator object 857 */ 858typedef void* ucl_object_iter_t; 859 860/** 861 * Get next key from an object 862 * @param obj object to iterate 863 * @param iter opaque iterator, must be set to NULL on the first call: 864 * ucl_object_iter_t it = NULL; 865 * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ... 866 * @return the next object or NULL 867 */ 868ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); 869/** @} */ 870 871 872/** 873 * @defgroup parser Parsing functions 874 * These functions are used to parse UCL objects 875 * 876 * @{ 877 */ 878 879/** 880 * Macro handler for a parser 881 * @param data the content of macro 882 * @param len the length of content 883 * @param ud opaque user data 884 * @param err error pointer 885 * @return true if macro has been parsed 886 */ 887typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud); 888 889/* Opaque parser */ 890struct ucl_parser; 891 892/** 893 * Creates new parser object 894 * @param pool pool to allocate memory from 895 * @return new parser object 896 */ 897struct ucl_parser* ucl_parser_new (int flags); 898 899/** 900 * Register new handler for a macro 901 * @param parser parser object 902 * @param macro macro name (without leading dot) 903 * @param handler handler (it is called immediately after macro is parsed) 904 * @param ud opaque user data for a handler 905 */ 906void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, 907 ucl_macro_handler handler, void* ud); 908 909/** 910 * Register new parser variable 911 * @param parser parser object 912 * @param var variable name 913 * @param value variable value 914 */ 915void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, 916 const char *value); 917 918/** 919 * Load new chunk to a parser 920 * @param parser parser structure 921 * @param data the pointer to the beginning of a chunk 922 * @param len the length of a chunk 923 * @param err if *err is NULL it is set to parser error 924 * @return true if chunk has been added and false in case of error 925 */ 926bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len); 927 928/** 929 * Load and add data from a file 930 * @param parser parser structure 931 * @param filename the name of file 932 * @param err if *err is NULL it is set to parser error 933 * @return true if chunk has been added and false in case of error 934 */ 935bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename); 936 937/** 938 * Get a top object for a parser 939 * @param parser parser structure 940 * @param err if *err is NULL it is set to parser error 941 * @return top parser object or NULL 942 */ 943ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); 944 945/** 946 * Get the error string if failing 947 * @param parser parser object 948 */ 949const char *ucl_parser_get_error(struct ucl_parser *parser); 950/** 951 * Free ucl parser object 952 * @param parser parser object 953 */ 954void ucl_parser_free (struct ucl_parser *parser); 955 956/** 957 * Add new public key to parser for signatures check 958 * @param parser parser object 959 * @param key PEM representation of a key 960 * @param len length of the key 961 * @param err if *err is NULL it is set to parser error 962 * @return true if a key has been successfully added 963 */ 964bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len); 965 966/** 967 * Set FILENAME and CURDIR variables in parser 968 * @param parser parser object 969 * @param filename filename to set or NULL to set FILENAME to "undef" and CURDIR to getcwd() 970 * @param need_expand perform realpath() if this variable is true and filename is not NULL 971 * @return true if variables has been set 972 */ 973bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, 974 bool need_expand); 975 976/** @} */ 977 978/** 979 * @defgroup emitter Emitting functions 980 * These functions are used to serialise UCL objects to some string representation. 981 * 982 * @{ 983 */ 984 985/** 986 * Structure using for emitter callbacks 987 */ 988struct ucl_emitter_functions { 989 /** Append a single character */ 990 int (*ucl_emitter_append_character) (unsigned char c, size_t nchars, void *ud); 991 /** Append a string of a specified length */ 992 int (*ucl_emitter_append_len) (unsigned const char *str, size_t len, void *ud); 993 /** Append a 64 bit integer */ 994 int (*ucl_emitter_append_int) (int64_t elt, void *ud); 995 /** Append floating point element */ 996 int (*ucl_emitter_append_double) (double elt, void *ud); 997 /** Opaque userdata pointer */ 998 void *ud; 999}; 1000 1001/** 1002 * Emit object to a string 1003 * @param obj object 1004 * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is 1005 * #UCL_EMIT_CONFIG then emit config like object 1006 * @return dump of an object (must be freed after using) or NULL in case of error 1007 */ 1008unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); 1009 1010/** 1011 * Emit object to a string 1012 * @param obj object 1013 * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is 1014 * #UCL_EMIT_CONFIG then emit config like object 1015 * @return dump of an object (must be freed after using) or NULL in case of error 1016 */ 1017bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, 1018 struct ucl_emitter_functions *emitter); 1019/** @} */ 1020 1021#ifdef __cplusplus 1022} 1023#endif 1024/* 1025 * XXX: Poorly named API functions, need to replace them with the appropriate 1026 * named function. All API functions *must* use naming ucl_object_*. Usage of 1027 * ucl_obj* should be avoided. 1028 */ 1029#define ucl_obj_todouble_safe ucl_object_todouble_safe 1030#define ucl_obj_todouble ucl_object_todouble 1031#define ucl_obj_tostring ucl_object_tostring 1032#define ucl_obj_tostring_safe ucl_object_tostring_safe 1033#define ucl_obj_tolstring ucl_object_tolstring 1034#define ucl_obj_tolstring_safe ucl_object_tolstring_safe 1035#define ucl_obj_toint ucl_object_toint 1036#define ucl_obj_toint_safe ucl_object_toint_safe 1037#define ucl_obj_toboolean ucl_object_toboolean 1038#define ucl_obj_toboolean_safe ucl_object_toboolean_safe 1039#define ucl_obj_get_key ucl_object_find_key 1040#define ucl_obj_get_keyl ucl_object_find_keyl 1041#define ucl_obj_unref ucl_object_unref 1042#define ucl_obj_ref ucl_object_ref 1043#define ucl_obj_free ucl_object_free 1044 1045#endif /* UCL_H_ */ 1046