ucl.h revision 262398
1/* Copyright (c) 2013, 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/** 36 * @mainpage 37 * This is a reference manual for UCL API. You may find the description of UCL format by following this 38 * [github repository](https://github.com/vstakhov/libucl). 39 * 40 * This manual has several main sections: 41 * - @ref structures 42 * - @ref utils 43 * - @ref parser 44 * - @ref emitter 45 */ 46 47/** 48 * @file ucl.h 49 * @brief UCL parsing and emitting functions 50 * 51 * UCL is universal configuration language, which is a form of 52 * JSON with less strict rules that make it more comfortable for 53 * using as a configuration language 54 */ 55#ifdef __cplusplus 56extern "C" { 57#endif 58/* 59 * Memory allocation utilities 60 * UCL_ALLOC(size) - allocate memory for UCL 61 * UCL_FREE(size, ptr) - free memory of specified size at ptr 62 * Default: malloc and free 63 */ 64#ifndef UCL_ALLOC 65#define UCL_ALLOC(size) malloc(size) 66#endif 67#ifndef UCL_FREE 68#define UCL_FREE(size, ptr) free(ptr) 69#endif 70 71#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) 72#define UCL_WARN_UNUSED_RESULT \ 73 __attribute__((warn_unused_result)) 74#else 75#define UCL_WARN_UNUSED_RESULT 76#endif 77 78/** 79 * @defgroup structures Structures and types 80 * UCL defines several enumeration types used for error reporting or specifying flags and attributes. 81 * 82 * @{ 83 */ 84 85/** 86 * The common error codes returned by ucl parser 87 */ 88typedef enum ucl_error { 89 UCL_EOK = 0, /**< No error */ 90 UCL_ESYNTAX, /**< Syntax error occurred during parsing */ 91 UCL_EIO, /**< IO error occurred during parsing */ 92 UCL_ESTATE, /**< Invalid state machine state */ 93 UCL_ENESTED, /**< Input has too many recursion levels */ 94 UCL_EMACRO, /**< Error processing a macro */ 95 UCL_EINTERNAL, /**< Internal unclassified error */ 96 UCL_ESSL /**< SSL error */ 97} ucl_error_t; 98 99/** 100 * #ucl_object_t may have one of specified types, some types are compatible with each other and some are not. 101 * For example, you can always convert #UCL_TIME to #UCL_FLOAT. Also you can convert #UCL_FLOAT to #UCL_INTEGER 102 * by loosing floating point. Every object may be converted to a string by #ucl_object_tostring_forced() function. 103 * 104 */ 105typedef enum ucl_type { 106 UCL_OBJECT = 0, /**< UCL object - key/value pairs */ 107 UCL_ARRAY, /**< UCL array */ 108 UCL_INT, /**< Integer number */ 109 UCL_FLOAT, /**< Floating point number */ 110 UCL_STRING, /**< Null terminated string */ 111 UCL_BOOLEAN, /**< Boolean value */ 112 UCL_TIME, /**< Time value (floating point number of seconds) */ 113 UCL_USERDATA, /**< Opaque userdata pointer (may be used in macros) */ 114 UCL_NULL /**< Null value */ 115} ucl_type_t; 116 117/** 118 * You can use one of these types to serialise #ucl_object_t by using ucl_object_emit(). 119 */ 120typedef enum ucl_emitter { 121 UCL_EMIT_JSON = 0, /**< Emit fine formatted JSON */ 122 UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */ 123 UCL_EMIT_CONFIG, /**< Emit human readable config format */ 124 UCL_EMIT_YAML /**< Emit embedded YAML format */ 125} ucl_emitter_t; 126 127/** 128 * These flags defines parser behaviour. If you specify #UCL_PARSER_ZEROCOPY you must ensure 129 * that the input memory is not freed if an object is in use. Moreover, if you want to use 130 * zero-terminated keys and string values then you should not use zero-copy mode, as in this case 131 * UCL still has to perform copying implicitly. 132 */ 133typedef enum ucl_parser_flags { 134 UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */ 135 UCL_PARSER_ZEROCOPY = 0x2 /**< Parse input in zero-copy mode if possible */ 136} ucl_parser_flags_t; 137 138/** 139 * String conversion flags, that are used in #ucl_object_fromstring_common function. 140 */ 141typedef enum ucl_string_flags { 142 UCL_STRING_ESCAPE = 0x1, /**< Perform JSON escape */ 143 UCL_STRING_TRIM = 0x2, /**< Trim leading and trailing whitespaces */ 144 UCL_STRING_PARSE_BOOLEAN = 0x4, /**< Parse passed string and detect boolean */ 145 UCL_STRING_PARSE_INT = 0x8, /**< Parse passed string and detect integer number */ 146 UCL_STRING_PARSE_DOUBLE = 0x10, /**< Parse passed string and detect integer or float number */ 147 UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE , /**< 148 Parse passed string and detect number */ 149 UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER, /**< 150 Parse passed string (and detect booleans and numbers) */ 151 UCL_STRING_PARSE_BYTES = 0x20 /**< Treat numbers as bytes */ 152} ucl_string_flags_t; 153 154/** 155 * Basic flags for an object 156 */ 157typedef enum ucl_object_flags { 158 UCL_OBJECT_ALLOCATED_KEY = 1, /**< An object has key allocated internally */ 159 UCL_OBJECT_ALLOCATED_VALUE = 2, /**< An object has a string value allocated internally */ 160 UCL_OBJECT_NEED_KEY_ESCAPE = 4 /**< The key of an object need to be escaped on output */ 161} ucl_object_flags_t; 162 163/** 164 * UCL object structure. Please mention that the most of fields should not be touched by 165 * UCL users. In future, this structure may be converted to private one. 166 */ 167typedef struct ucl_object_s { 168 /** 169 * Variant value type 170 */ 171 union { 172 int64_t iv; /**< Int value of an object */ 173 const char *sv; /**< String value of an object */ 174 double dv; /**< Double value of an object */ 175 struct ucl_object_s *av; /**< Array */ 176 void *ov; /**< Object */ 177 void* ud; /**< Opaque user data */ 178 } value; 179 const char *key; /**< Key of an object */ 180 struct ucl_object_s *next; /**< Array handle */ 181 struct ucl_object_s *prev; /**< Array handle */ 182 unsigned char* trash_stack[2]; /**< Pointer to allocated chunks */ 183 unsigned keylen; /**< Lenght of a key */ 184 unsigned len; /**< Size of an object */ 185 enum ucl_type type; /**< Real type */ 186 uint16_t ref; /**< Reference count */ 187 uint16_t flags; /**< Object flags */ 188} ucl_object_t; 189 190/** @} */ 191 192/** 193 * @defgroup utils Utility functions 194 * A number of utility functions simplify handling of UCL objects 195 * 196 * @{ 197 */ 198/** 199 * Copy and return a key of an object, returned key is zero-terminated 200 * @param obj CL object 201 * @return zero terminated key 202 */ 203char* ucl_copy_key_trash (ucl_object_t *obj); 204 205/** 206 * Copy and return a string value of an object, returned key is zero-terminated 207 * @param obj CL object 208 * @return zero terminated string representation of object value 209 */ 210char* ucl_copy_value_trash (ucl_object_t *obj); 211 212/** 213 * Creates a new object 214 * @return new object 215 */ 216static inline ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT; 217static inline ucl_object_t * 218ucl_object_new (void) 219{ 220 ucl_object_t *new; 221 new = malloc (sizeof (ucl_object_t)); 222 if (new != NULL) { 223 memset (new, 0, sizeof (ucl_object_t)); 224 new->ref = 1; 225 new->type = UCL_NULL; 226 } 227 return new; 228} 229 230/** 231 * Create new object with type specified 232 * @param type type of a new object 233 * @return new object 234 */ 235static inline ucl_object_t* ucl_object_typed_new (unsigned int type) UCL_WARN_UNUSED_RESULT; 236static inline ucl_object_t * 237ucl_object_typed_new (unsigned int type) 238{ 239 ucl_object_t *new; 240 new = malloc (sizeof (ucl_object_t)); 241 if (new != NULL) { 242 memset (new, 0, sizeof (ucl_object_t)); 243 new->ref = 1; 244 new->type = (type <= UCL_NULL ? type : UCL_NULL); 245 } 246 return new; 247} 248 249/** 250 * Convert any string to an ucl object making the specified transformations 251 * @param str fixed size or NULL terminated string 252 * @param len length (if len is zero, than str is treated as NULL terminated) 253 * @param flags conversion flags 254 * @return new object 255 */ 256ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, 257 enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT; 258 259/** 260 * Create a UCL object from the specified string 261 * @param str NULL terminated string, will be json escaped 262 * @return new object 263 */ 264static inline ucl_object_t * 265ucl_object_fromstring (const char *str) 266{ 267 return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE); 268} 269 270/** 271 * Create a UCL object from the specified string 272 * @param str fixed size string, will be json escaped 273 * @param len length of a string 274 * @return new object 275 */ 276static inline ucl_object_t * 277ucl_object_fromlstring (const char *str, size_t len) 278{ 279 return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE); 280} 281 282/** 283 * Create an object from an integer number 284 * @param iv number 285 * @return new object 286 */ 287static inline ucl_object_t * 288ucl_object_fromint (int64_t iv) 289{ 290 ucl_object_t *obj; 291 292 obj = ucl_object_new (); 293 if (obj != NULL) { 294 obj->type = UCL_INT; 295 obj->value.iv = iv; 296 } 297 298 return obj; 299} 300 301/** 302 * Create an object from a float number 303 * @param dv number 304 * @return new object 305 */ 306static inline ucl_object_t * 307ucl_object_fromdouble (double dv) 308{ 309 ucl_object_t *obj; 310 311 obj = ucl_object_new (); 312 if (obj != NULL) { 313 obj->type = UCL_FLOAT; 314 obj->value.dv = dv; 315 } 316 317 return obj; 318} 319 320/** 321 * Create an object from a boolean 322 * @param bv bool value 323 * @return new object 324 */ 325static inline ucl_object_t * 326ucl_object_frombool (bool bv) 327{ 328 ucl_object_t *obj; 329 330 obj = ucl_object_new (); 331 if (obj != NULL) { 332 obj->type = UCL_BOOLEAN; 333 obj->value.iv = bv; 334 } 335 336 return obj; 337} 338 339/** 340 * Insert a object 'elt' to the hash 'top' and associate it with key 'key' 341 * @param top destination object (will be created automatically if top is NULL) 342 * @param elt element to insert (must NOT be NULL) 343 * @param key key to associate with this object (either const or preallocated) 344 * @param keylen length of the key (or 0 for NULL terminated keys) 345 * @param copy_key make an internal copy of key 346 * @return new value of top object 347 */ 348ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, 349 const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 350 351/** 352 * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed, 353 * if no object has been found this function works like ucl_object_insert_key() 354 * @param top destination object (will be created automatically if top is NULL) 355 * @param elt element to insert (must NOT be NULL) 356 * @param key key to associate with this object (either const or preallocated) 357 * @param keylen length of the key (or 0 for NULL terminated keys) 358 * @param copy_key make an internal copy of key 359 * @return new value of top object 360 */ 361ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, 362 const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 363 364/** 365 * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, 366 * try to merge its content 367 * @param top destination object (will be created automatically if top is NULL) 368 * @param elt element to insert (must NOT be NULL) 369 * @param key key to associate with this object (either const or preallocated) 370 * @param keylen length of the key (or 0 for NULL terminated keys) 371 * @param copy_key make an internal copy of key 372 * @return new value of top object 373 */ 374ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, 375 const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 376 377/** 378 * Append an element to the front of array object 379 * @param top destination object (will be created automatically if top is NULL) 380 * @param elt element to append (must NOT be NULL) 381 * @return new value of top object 382 */ 383static inline ucl_object_t * ucl_array_append (ucl_object_t *top, 384 ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; 385static inline ucl_object_t * 386ucl_array_append (ucl_object_t *top, ucl_object_t *elt) 387{ 388 ucl_object_t *head; 389 390 if (elt == NULL) { 391 return NULL; 392 } 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