1*c99fb5f9SBaptiste Daroussin /* Copyright (c) 2013, Vsevolod Stakhov 2*c99fb5f9SBaptiste Daroussin * All rights reserved. 3*c99fb5f9SBaptiste Daroussin * 4*c99fb5f9SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 5*c99fb5f9SBaptiste Daroussin * modification, are permitted provided that the following conditions are met: 6*c99fb5f9SBaptiste Daroussin * * Redistributions of source code must retain the above copyright 7*c99fb5f9SBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 8*c99fb5f9SBaptiste Daroussin * * Redistributions in binary form must reproduce the above copyright 9*c99fb5f9SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 10*c99fb5f9SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 11*c99fb5f9SBaptiste Daroussin * 12*c99fb5f9SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY 13*c99fb5f9SBaptiste Daroussin * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14*c99fb5f9SBaptiste Daroussin * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15*c99fb5f9SBaptiste Daroussin * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY 16*c99fb5f9SBaptiste Daroussin * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17*c99fb5f9SBaptiste Daroussin * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18*c99fb5f9SBaptiste Daroussin * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19*c99fb5f9SBaptiste Daroussin * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20*c99fb5f9SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21*c99fb5f9SBaptiste Daroussin * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22*c99fb5f9SBaptiste Daroussin */ 23*c99fb5f9SBaptiste Daroussin 24*c99fb5f9SBaptiste Daroussin #ifndef UCL_H_ 25*c99fb5f9SBaptiste Daroussin #define UCL_H_ 26*c99fb5f9SBaptiste Daroussin 27*c99fb5f9SBaptiste Daroussin #include <string.h> 28*c99fb5f9SBaptiste Daroussin #include <stddef.h> 29*c99fb5f9SBaptiste Daroussin #include <stdlib.h> 30*c99fb5f9SBaptiste Daroussin #include <stdint.h> 31*c99fb5f9SBaptiste Daroussin #include <stdbool.h> 32*c99fb5f9SBaptiste Daroussin #include <stdarg.h> 33*c99fb5f9SBaptiste Daroussin #include <stdio.h> 34*c99fb5f9SBaptiste Daroussin 35*c99fb5f9SBaptiste Daroussin /** 36*c99fb5f9SBaptiste Daroussin * @mainpage 37*c99fb5f9SBaptiste Daroussin * This is a reference manual for UCL API. You may find the description of UCL format by following this 38*c99fb5f9SBaptiste Daroussin * [github repository](https://github.com/vstakhov/libucl). 39*c99fb5f9SBaptiste Daroussin * 40*c99fb5f9SBaptiste Daroussin * This manual has several main sections: 41*c99fb5f9SBaptiste Daroussin * - @ref structures 42*c99fb5f9SBaptiste Daroussin * - @ref utils 43*c99fb5f9SBaptiste Daroussin * - @ref parser 44*c99fb5f9SBaptiste Daroussin * - @ref emitter 45*c99fb5f9SBaptiste Daroussin */ 46*c99fb5f9SBaptiste Daroussin 47*c99fb5f9SBaptiste Daroussin /** 48*c99fb5f9SBaptiste Daroussin * @file ucl.h 49*c99fb5f9SBaptiste Daroussin * @brief UCL parsing and emitting functions 50*c99fb5f9SBaptiste Daroussin * 51*c99fb5f9SBaptiste Daroussin * UCL is universal configuration language, which is a form of 52*c99fb5f9SBaptiste Daroussin * JSON with less strict rules that make it more comfortable for 53*c99fb5f9SBaptiste Daroussin * using as a configuration language 54*c99fb5f9SBaptiste Daroussin */ 55*c99fb5f9SBaptiste Daroussin #ifdef __cplusplus 56*c99fb5f9SBaptiste Daroussin extern "C" { 57*c99fb5f9SBaptiste Daroussin #endif 58*c99fb5f9SBaptiste Daroussin /* 59*c99fb5f9SBaptiste Daroussin * Memory allocation utilities 60*c99fb5f9SBaptiste Daroussin * UCL_ALLOC(size) - allocate memory for UCL 61*c99fb5f9SBaptiste Daroussin * UCL_FREE(size, ptr) - free memory of specified size at ptr 62*c99fb5f9SBaptiste Daroussin * Default: malloc and free 63*c99fb5f9SBaptiste Daroussin */ 64*c99fb5f9SBaptiste Daroussin #ifndef UCL_ALLOC 65*c99fb5f9SBaptiste Daroussin #define UCL_ALLOC(size) malloc(size) 66*c99fb5f9SBaptiste Daroussin #endif 67*c99fb5f9SBaptiste Daroussin #ifndef UCL_FREE 68*c99fb5f9SBaptiste Daroussin #define UCL_FREE(size, ptr) free(ptr) 69*c99fb5f9SBaptiste Daroussin #endif 70*c99fb5f9SBaptiste Daroussin 71*c99fb5f9SBaptiste Daroussin #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) 72*c99fb5f9SBaptiste Daroussin #define UCL_WARN_UNUSED_RESULT \ 73*c99fb5f9SBaptiste Daroussin __attribute__((warn_unused_result)) 74*c99fb5f9SBaptiste Daroussin #else 75*c99fb5f9SBaptiste Daroussin #define UCL_WARN_UNUSED_RESULT 76*c99fb5f9SBaptiste Daroussin #endif 77*c99fb5f9SBaptiste Daroussin 78*c99fb5f9SBaptiste Daroussin /** 79*c99fb5f9SBaptiste Daroussin * @defgroup structures Structures and types 80*c99fb5f9SBaptiste Daroussin * UCL defines several enumeration types used for error reporting or specifying flags and attributes. 81*c99fb5f9SBaptiste Daroussin * 82*c99fb5f9SBaptiste Daroussin * @{ 83*c99fb5f9SBaptiste Daroussin */ 84*c99fb5f9SBaptiste Daroussin 85*c99fb5f9SBaptiste Daroussin /** 86*c99fb5f9SBaptiste Daroussin * The common error codes returned by ucl parser 87*c99fb5f9SBaptiste Daroussin */ 88*c99fb5f9SBaptiste Daroussin typedef enum ucl_error { 89*c99fb5f9SBaptiste Daroussin UCL_EOK = 0, /**< No error */ 90*c99fb5f9SBaptiste Daroussin UCL_ESYNTAX, /**< Syntax error occurred during parsing */ 91*c99fb5f9SBaptiste Daroussin UCL_EIO, /**< IO error occurred during parsing */ 92*c99fb5f9SBaptiste Daroussin UCL_ESTATE, /**< Invalid state machine state */ 93*c99fb5f9SBaptiste Daroussin UCL_ENESTED, /**< Input has too many recursion levels */ 94*c99fb5f9SBaptiste Daroussin UCL_EMACRO, /**< Error processing a macro */ 95*c99fb5f9SBaptiste Daroussin UCL_EINTERNAL, /**< Internal unclassified error */ 96*c99fb5f9SBaptiste Daroussin UCL_ESSL /**< SSL error */ 97*c99fb5f9SBaptiste Daroussin } ucl_error_t; 98*c99fb5f9SBaptiste Daroussin 99*c99fb5f9SBaptiste Daroussin /** 100*c99fb5f9SBaptiste Daroussin * #ucl_object_t may have one of specified types, some types are compatible with each other and some are not. 101*c99fb5f9SBaptiste Daroussin * For example, you can always convert #UCL_TIME to #UCL_FLOAT. Also you can convert #UCL_FLOAT to #UCL_INTEGER 102*c99fb5f9SBaptiste Daroussin * by loosing floating point. Every object may be converted to a string by #ucl_object_tostring_forced() function. 103*c99fb5f9SBaptiste Daroussin * 104*c99fb5f9SBaptiste Daroussin */ 105*c99fb5f9SBaptiste Daroussin typedef enum ucl_type { 106*c99fb5f9SBaptiste Daroussin UCL_OBJECT = 0, /**< UCL object - key/value pairs */ 107*c99fb5f9SBaptiste Daroussin UCL_ARRAY, /**< UCL array */ 108*c99fb5f9SBaptiste Daroussin UCL_INT, /**< Integer number */ 109*c99fb5f9SBaptiste Daroussin UCL_FLOAT, /**< Floating point number */ 110*c99fb5f9SBaptiste Daroussin UCL_STRING, /**< Null terminated string */ 111*c99fb5f9SBaptiste Daroussin UCL_BOOLEAN, /**< Boolean value */ 112*c99fb5f9SBaptiste Daroussin UCL_TIME, /**< Time value (floating point number of seconds) */ 113*c99fb5f9SBaptiste Daroussin UCL_USERDATA, /**< Opaque userdata pointer (may be used in macros) */ 114*c99fb5f9SBaptiste Daroussin UCL_NULL /**< Null value */ 115*c99fb5f9SBaptiste Daroussin } ucl_type_t; 116*c99fb5f9SBaptiste Daroussin 117*c99fb5f9SBaptiste Daroussin /** 118*c99fb5f9SBaptiste Daroussin * You can use one of these types to serialise #ucl_object_t by using ucl_object_emit(). 119*c99fb5f9SBaptiste Daroussin */ 120*c99fb5f9SBaptiste Daroussin typedef enum ucl_emitter { 121*c99fb5f9SBaptiste Daroussin UCL_EMIT_JSON = 0, /**< Emit fine formatted JSON */ 122*c99fb5f9SBaptiste Daroussin UCL_EMIT_JSON_COMPACT, /**< Emit compacted JSON */ 123*c99fb5f9SBaptiste Daroussin UCL_EMIT_CONFIG, /**< Emit human readable config format */ 124*c99fb5f9SBaptiste Daroussin UCL_EMIT_YAML /**< Emit embedded YAML format */ 125*c99fb5f9SBaptiste Daroussin } ucl_emitter_t; 126*c99fb5f9SBaptiste Daroussin 127*c99fb5f9SBaptiste Daroussin /** 128*c99fb5f9SBaptiste Daroussin * These flags defines parser behaviour. If you specify #UCL_PARSER_ZEROCOPY you must ensure 129*c99fb5f9SBaptiste Daroussin * that the input memory is not freed if an object is in use. Moreover, if you want to use 130*c99fb5f9SBaptiste Daroussin * zero-terminated keys and string values then you should not use zero-copy mode, as in this case 131*c99fb5f9SBaptiste Daroussin * UCL still has to perform copying implicitly. 132*c99fb5f9SBaptiste Daroussin */ 133*c99fb5f9SBaptiste Daroussin typedef enum ucl_parser_flags { 134*c99fb5f9SBaptiste Daroussin UCL_PARSER_KEY_LOWERCASE = 0x1, /**< Convert all keys to lower case */ 135*c99fb5f9SBaptiste Daroussin UCL_PARSER_ZEROCOPY = 0x2 /**< Parse input in zero-copy mode if possible */ 136*c99fb5f9SBaptiste Daroussin } ucl_parser_flags_t; 137*c99fb5f9SBaptiste Daroussin 138*c99fb5f9SBaptiste Daroussin /** 139*c99fb5f9SBaptiste Daroussin * String conversion flags, that are used in #ucl_object_fromstring_common function. 140*c99fb5f9SBaptiste Daroussin */ 141*c99fb5f9SBaptiste Daroussin typedef enum ucl_string_flags { 142*c99fb5f9SBaptiste Daroussin UCL_STRING_ESCAPE = 0x1, /**< Perform JSON escape */ 143*c99fb5f9SBaptiste Daroussin UCL_STRING_TRIM = 0x2, /**< Trim leading and trailing whitespaces */ 144*c99fb5f9SBaptiste Daroussin UCL_STRING_PARSE_BOOLEAN = 0x4, /**< Parse passed string and detect boolean */ 145*c99fb5f9SBaptiste Daroussin UCL_STRING_PARSE_INT = 0x8, /**< Parse passed string and detect integer number */ 146*c99fb5f9SBaptiste Daroussin UCL_STRING_PARSE_DOUBLE = 0x10, /**< Parse passed string and detect integer or float number */ 147*c99fb5f9SBaptiste Daroussin UCL_STRING_PARSE_NUMBER = UCL_STRING_PARSE_INT|UCL_STRING_PARSE_DOUBLE , /**< 148*c99fb5f9SBaptiste Daroussin Parse passed string and detect number */ 149*c99fb5f9SBaptiste Daroussin UCL_STRING_PARSE = UCL_STRING_PARSE_BOOLEAN|UCL_STRING_PARSE_NUMBER, /**< 150*c99fb5f9SBaptiste Daroussin Parse passed string (and detect booleans and numbers) */ 151*c99fb5f9SBaptiste Daroussin UCL_STRING_PARSE_BYTES = 0x20 /**< Treat numbers as bytes */ 152*c99fb5f9SBaptiste Daroussin } ucl_string_flags_t; 153*c99fb5f9SBaptiste Daroussin 154*c99fb5f9SBaptiste Daroussin /** 155*c99fb5f9SBaptiste Daroussin * Basic flags for an object 156*c99fb5f9SBaptiste Daroussin */ 157*c99fb5f9SBaptiste Daroussin typedef enum ucl_object_flags { 158*c99fb5f9SBaptiste Daroussin UCL_OBJECT_ALLOCATED_KEY = 1, /**< An object has key allocated internally */ 159*c99fb5f9SBaptiste Daroussin UCL_OBJECT_ALLOCATED_VALUE = 2, /**< An object has a string value allocated internally */ 160*c99fb5f9SBaptiste Daroussin UCL_OBJECT_NEED_KEY_ESCAPE = 4 /**< The key of an object need to be escaped on output */ 161*c99fb5f9SBaptiste Daroussin } ucl_object_flags_t; 162*c99fb5f9SBaptiste Daroussin 163*c99fb5f9SBaptiste Daroussin /** 164*c99fb5f9SBaptiste Daroussin * UCL object structure. Please mention that the most of fields should not be touched by 165*c99fb5f9SBaptiste Daroussin * UCL users. In future, this structure may be converted to private one. 166*c99fb5f9SBaptiste Daroussin */ 167*c99fb5f9SBaptiste Daroussin typedef struct ucl_object_s { 168*c99fb5f9SBaptiste Daroussin /** 169*c99fb5f9SBaptiste Daroussin * Variant value type 170*c99fb5f9SBaptiste Daroussin */ 171*c99fb5f9SBaptiste Daroussin union { 172*c99fb5f9SBaptiste Daroussin int64_t iv; /**< Int value of an object */ 173*c99fb5f9SBaptiste Daroussin const char *sv; /**< String value of an object */ 174*c99fb5f9SBaptiste Daroussin double dv; /**< Double value of an object */ 175*c99fb5f9SBaptiste Daroussin struct ucl_object_s *av; /**< Array */ 176*c99fb5f9SBaptiste Daroussin void *ov; /**< Object */ 177*c99fb5f9SBaptiste Daroussin void* ud; /**< Opaque user data */ 178*c99fb5f9SBaptiste Daroussin } value; 179*c99fb5f9SBaptiste Daroussin const char *key; /**< Key of an object */ 180*c99fb5f9SBaptiste Daroussin struct ucl_object_s *next; /**< Array handle */ 181*c99fb5f9SBaptiste Daroussin struct ucl_object_s *prev; /**< Array handle */ 182*c99fb5f9SBaptiste Daroussin unsigned char* trash_stack[2]; /**< Pointer to allocated chunks */ 183*c99fb5f9SBaptiste Daroussin unsigned keylen; /**< Lenght of a key */ 184*c99fb5f9SBaptiste Daroussin unsigned len; /**< Size of an object */ 185*c99fb5f9SBaptiste Daroussin enum ucl_type type; /**< Real type */ 186*c99fb5f9SBaptiste Daroussin uint16_t ref; /**< Reference count */ 187*c99fb5f9SBaptiste Daroussin uint16_t flags; /**< Object flags */ 188*c99fb5f9SBaptiste Daroussin } ucl_object_t; 189*c99fb5f9SBaptiste Daroussin 190*c99fb5f9SBaptiste Daroussin /** @} */ 191*c99fb5f9SBaptiste Daroussin 192*c99fb5f9SBaptiste Daroussin /** 193*c99fb5f9SBaptiste Daroussin * @defgroup utils Utility functions 194*c99fb5f9SBaptiste Daroussin * A number of utility functions simplify handling of UCL objects 195*c99fb5f9SBaptiste Daroussin * 196*c99fb5f9SBaptiste Daroussin * @{ 197*c99fb5f9SBaptiste Daroussin */ 198*c99fb5f9SBaptiste Daroussin /** 199*c99fb5f9SBaptiste Daroussin * Copy and return a key of an object, returned key is zero-terminated 200*c99fb5f9SBaptiste Daroussin * @param obj CL object 201*c99fb5f9SBaptiste Daroussin * @return zero terminated key 202*c99fb5f9SBaptiste Daroussin */ 203*c99fb5f9SBaptiste Daroussin char* ucl_copy_key_trash (ucl_object_t *obj); 204*c99fb5f9SBaptiste Daroussin 205*c99fb5f9SBaptiste Daroussin /** 206*c99fb5f9SBaptiste Daroussin * Copy and return a string value of an object, returned key is zero-terminated 207*c99fb5f9SBaptiste Daroussin * @param obj CL object 208*c99fb5f9SBaptiste Daroussin * @return zero terminated string representation of object value 209*c99fb5f9SBaptiste Daroussin */ 210*c99fb5f9SBaptiste Daroussin char* ucl_copy_value_trash (ucl_object_t *obj); 211*c99fb5f9SBaptiste Daroussin 212*c99fb5f9SBaptiste Daroussin /** 213*c99fb5f9SBaptiste Daroussin * Creates a new object 214*c99fb5f9SBaptiste Daroussin * @return new object 215*c99fb5f9SBaptiste Daroussin */ 216*c99fb5f9SBaptiste Daroussin static inline ucl_object_t* ucl_object_new (void) UCL_WARN_UNUSED_RESULT; 217*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 218*c99fb5f9SBaptiste Daroussin ucl_object_new (void) 219*c99fb5f9SBaptiste Daroussin { 220*c99fb5f9SBaptiste Daroussin ucl_object_t *new; 221*c99fb5f9SBaptiste Daroussin new = malloc (sizeof (ucl_object_t)); 222*c99fb5f9SBaptiste Daroussin if (new != NULL) { 223*c99fb5f9SBaptiste Daroussin memset (new, 0, sizeof (ucl_object_t)); 224*c99fb5f9SBaptiste Daroussin new->ref = 1; 225*c99fb5f9SBaptiste Daroussin new->type = UCL_NULL; 226*c99fb5f9SBaptiste Daroussin } 227*c99fb5f9SBaptiste Daroussin return new; 228*c99fb5f9SBaptiste Daroussin } 229*c99fb5f9SBaptiste Daroussin 230*c99fb5f9SBaptiste Daroussin /** 231*c99fb5f9SBaptiste Daroussin * Create new object with type specified 232*c99fb5f9SBaptiste Daroussin * @param type type of a new object 233*c99fb5f9SBaptiste Daroussin * @return new object 234*c99fb5f9SBaptiste Daroussin */ 235*c99fb5f9SBaptiste Daroussin static inline ucl_object_t* ucl_object_typed_new (unsigned int type) UCL_WARN_UNUSED_RESULT; 236*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 237*c99fb5f9SBaptiste Daroussin ucl_object_typed_new (unsigned int type) 238*c99fb5f9SBaptiste Daroussin { 239*c99fb5f9SBaptiste Daroussin ucl_object_t *new; 240*c99fb5f9SBaptiste Daroussin new = malloc (sizeof (ucl_object_t)); 241*c99fb5f9SBaptiste Daroussin if (new != NULL) { 242*c99fb5f9SBaptiste Daroussin memset (new, 0, sizeof (ucl_object_t)); 243*c99fb5f9SBaptiste Daroussin new->ref = 1; 244*c99fb5f9SBaptiste Daroussin new->type = (type <= UCL_NULL ? type : UCL_NULL); 245*c99fb5f9SBaptiste Daroussin } 246*c99fb5f9SBaptiste Daroussin return new; 247*c99fb5f9SBaptiste Daroussin } 248*c99fb5f9SBaptiste Daroussin 249*c99fb5f9SBaptiste Daroussin /** 250*c99fb5f9SBaptiste Daroussin * Convert any string to an ucl object making the specified transformations 251*c99fb5f9SBaptiste Daroussin * @param str fixed size or NULL terminated string 252*c99fb5f9SBaptiste Daroussin * @param len length (if len is zero, than str is treated as NULL terminated) 253*c99fb5f9SBaptiste Daroussin * @param flags conversion flags 254*c99fb5f9SBaptiste Daroussin * @return new object 255*c99fb5f9SBaptiste Daroussin */ 256*c99fb5f9SBaptiste Daroussin ucl_object_t * ucl_object_fromstring_common (const char *str, size_t len, 257*c99fb5f9SBaptiste Daroussin enum ucl_string_flags flags) UCL_WARN_UNUSED_RESULT; 258*c99fb5f9SBaptiste Daroussin 259*c99fb5f9SBaptiste Daroussin /** 260*c99fb5f9SBaptiste Daroussin * Create a UCL object from the specified string 261*c99fb5f9SBaptiste Daroussin * @param str NULL terminated string, will be json escaped 262*c99fb5f9SBaptiste Daroussin * @return new object 263*c99fb5f9SBaptiste Daroussin */ 264*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 265*c99fb5f9SBaptiste Daroussin ucl_object_fromstring (const char *str) 266*c99fb5f9SBaptiste Daroussin { 267*c99fb5f9SBaptiste Daroussin return ucl_object_fromstring_common (str, 0, UCL_STRING_ESCAPE); 268*c99fb5f9SBaptiste Daroussin } 269*c99fb5f9SBaptiste Daroussin 270*c99fb5f9SBaptiste Daroussin /** 271*c99fb5f9SBaptiste Daroussin * Create a UCL object from the specified string 272*c99fb5f9SBaptiste Daroussin * @param str fixed size string, will be json escaped 273*c99fb5f9SBaptiste Daroussin * @param len length of a string 274*c99fb5f9SBaptiste Daroussin * @return new object 275*c99fb5f9SBaptiste Daroussin */ 276*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 277*c99fb5f9SBaptiste Daroussin ucl_object_fromlstring (const char *str, size_t len) 278*c99fb5f9SBaptiste Daroussin { 279*c99fb5f9SBaptiste Daroussin return ucl_object_fromstring_common (str, len, UCL_STRING_ESCAPE); 280*c99fb5f9SBaptiste Daroussin } 281*c99fb5f9SBaptiste Daroussin 282*c99fb5f9SBaptiste Daroussin /** 283*c99fb5f9SBaptiste Daroussin * Create an object from an integer number 284*c99fb5f9SBaptiste Daroussin * @param iv number 285*c99fb5f9SBaptiste Daroussin * @return new object 286*c99fb5f9SBaptiste Daroussin */ 287*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 288*c99fb5f9SBaptiste Daroussin ucl_object_fromint (int64_t iv) 289*c99fb5f9SBaptiste Daroussin { 290*c99fb5f9SBaptiste Daroussin ucl_object_t *obj; 291*c99fb5f9SBaptiste Daroussin 292*c99fb5f9SBaptiste Daroussin obj = ucl_object_new (); 293*c99fb5f9SBaptiste Daroussin if (obj != NULL) { 294*c99fb5f9SBaptiste Daroussin obj->type = UCL_INT; 295*c99fb5f9SBaptiste Daroussin obj->value.iv = iv; 296*c99fb5f9SBaptiste Daroussin } 297*c99fb5f9SBaptiste Daroussin 298*c99fb5f9SBaptiste Daroussin return obj; 299*c99fb5f9SBaptiste Daroussin } 300*c99fb5f9SBaptiste Daroussin 301*c99fb5f9SBaptiste Daroussin /** 302*c99fb5f9SBaptiste Daroussin * Create an object from a float number 303*c99fb5f9SBaptiste Daroussin * @param dv number 304*c99fb5f9SBaptiste Daroussin * @return new object 305*c99fb5f9SBaptiste Daroussin */ 306*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 307*c99fb5f9SBaptiste Daroussin ucl_object_fromdouble (double dv) 308*c99fb5f9SBaptiste Daroussin { 309*c99fb5f9SBaptiste Daroussin ucl_object_t *obj; 310*c99fb5f9SBaptiste Daroussin 311*c99fb5f9SBaptiste Daroussin obj = ucl_object_new (); 312*c99fb5f9SBaptiste Daroussin if (obj != NULL) { 313*c99fb5f9SBaptiste Daroussin obj->type = UCL_FLOAT; 314*c99fb5f9SBaptiste Daroussin obj->value.dv = dv; 315*c99fb5f9SBaptiste Daroussin } 316*c99fb5f9SBaptiste Daroussin 317*c99fb5f9SBaptiste Daroussin return obj; 318*c99fb5f9SBaptiste Daroussin } 319*c99fb5f9SBaptiste Daroussin 320*c99fb5f9SBaptiste Daroussin /** 321*c99fb5f9SBaptiste Daroussin * Create an object from a boolean 322*c99fb5f9SBaptiste Daroussin * @param bv bool value 323*c99fb5f9SBaptiste Daroussin * @return new object 324*c99fb5f9SBaptiste Daroussin */ 325*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 326*c99fb5f9SBaptiste Daroussin ucl_object_frombool (bool bv) 327*c99fb5f9SBaptiste Daroussin { 328*c99fb5f9SBaptiste Daroussin ucl_object_t *obj; 329*c99fb5f9SBaptiste Daroussin 330*c99fb5f9SBaptiste Daroussin obj = ucl_object_new (); 331*c99fb5f9SBaptiste Daroussin if (obj != NULL) { 332*c99fb5f9SBaptiste Daroussin obj->type = UCL_BOOLEAN; 333*c99fb5f9SBaptiste Daroussin obj->value.iv = bv; 334*c99fb5f9SBaptiste Daroussin } 335*c99fb5f9SBaptiste Daroussin 336*c99fb5f9SBaptiste Daroussin return obj; 337*c99fb5f9SBaptiste Daroussin } 338*c99fb5f9SBaptiste Daroussin 339*c99fb5f9SBaptiste Daroussin /** 340*c99fb5f9SBaptiste Daroussin * Insert a object 'elt' to the hash 'top' and associate it with key 'key' 341*c99fb5f9SBaptiste Daroussin * @param top destination object (will be created automatically if top is NULL) 342*c99fb5f9SBaptiste Daroussin * @param elt element to insert (must NOT be NULL) 343*c99fb5f9SBaptiste Daroussin * @param key key to associate with this object (either const or preallocated) 344*c99fb5f9SBaptiste Daroussin * @param keylen length of the key (or 0 for NULL terminated keys) 345*c99fb5f9SBaptiste Daroussin * @param copy_key make an internal copy of key 346*c99fb5f9SBaptiste Daroussin * @return new value of top object 347*c99fb5f9SBaptiste Daroussin */ 348*c99fb5f9SBaptiste Daroussin ucl_object_t* ucl_object_insert_key (ucl_object_t *top, ucl_object_t *elt, 349*c99fb5f9SBaptiste Daroussin const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 350*c99fb5f9SBaptiste Daroussin 351*c99fb5f9SBaptiste Daroussin /** 352*c99fb5f9SBaptiste Daroussin * Replace a object 'elt' to the hash 'top' and associate it with key 'key', old object will be unrefed, 353*c99fb5f9SBaptiste Daroussin * if no object has been found this function works like ucl_object_insert_key() 354*c99fb5f9SBaptiste Daroussin * @param top destination object (will be created automatically if top is NULL) 355*c99fb5f9SBaptiste Daroussin * @param elt element to insert (must NOT be NULL) 356*c99fb5f9SBaptiste Daroussin * @param key key to associate with this object (either const or preallocated) 357*c99fb5f9SBaptiste Daroussin * @param keylen length of the key (or 0 for NULL terminated keys) 358*c99fb5f9SBaptiste Daroussin * @param copy_key make an internal copy of key 359*c99fb5f9SBaptiste Daroussin * @return new value of top object 360*c99fb5f9SBaptiste Daroussin */ 361*c99fb5f9SBaptiste Daroussin ucl_object_t* ucl_object_replace_key (ucl_object_t *top, ucl_object_t *elt, 362*c99fb5f9SBaptiste Daroussin const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 363*c99fb5f9SBaptiste Daroussin 364*c99fb5f9SBaptiste Daroussin /** 365*c99fb5f9SBaptiste Daroussin * Insert a object 'elt' to the hash 'top' and associate it with key 'key', if the specified key exist, 366*c99fb5f9SBaptiste Daroussin * try to merge its content 367*c99fb5f9SBaptiste Daroussin * @param top destination object (will be created automatically if top is NULL) 368*c99fb5f9SBaptiste Daroussin * @param elt element to insert (must NOT be NULL) 369*c99fb5f9SBaptiste Daroussin * @param key key to associate with this object (either const or preallocated) 370*c99fb5f9SBaptiste Daroussin * @param keylen length of the key (or 0 for NULL terminated keys) 371*c99fb5f9SBaptiste Daroussin * @param copy_key make an internal copy of key 372*c99fb5f9SBaptiste Daroussin * @return new value of top object 373*c99fb5f9SBaptiste Daroussin */ 374*c99fb5f9SBaptiste Daroussin ucl_object_t* ucl_object_insert_key_merged (ucl_object_t *top, ucl_object_t *elt, 375*c99fb5f9SBaptiste Daroussin const char *key, size_t keylen, bool copy_key) UCL_WARN_UNUSED_RESULT; 376*c99fb5f9SBaptiste Daroussin 377*c99fb5f9SBaptiste Daroussin /** 378*c99fb5f9SBaptiste Daroussin * Append an element to the front of array object 379*c99fb5f9SBaptiste Daroussin * @param top destination object (will be created automatically if top is NULL) 380*c99fb5f9SBaptiste Daroussin * @param elt element to append (must NOT be NULL) 381*c99fb5f9SBaptiste Daroussin * @return new value of top object 382*c99fb5f9SBaptiste Daroussin */ 383*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * ucl_array_append (ucl_object_t *top, 384*c99fb5f9SBaptiste Daroussin ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; 385*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 386*c99fb5f9SBaptiste Daroussin ucl_array_append (ucl_object_t *top, ucl_object_t *elt) 387*c99fb5f9SBaptiste Daroussin { 388*c99fb5f9SBaptiste Daroussin ucl_object_t *head; 389*c99fb5f9SBaptiste Daroussin 390*c99fb5f9SBaptiste Daroussin if (elt == NULL) { 391*c99fb5f9SBaptiste Daroussin return NULL; 392*c99fb5f9SBaptiste Daroussin } 393*c99fb5f9SBaptiste Daroussin 394*c99fb5f9SBaptiste Daroussin if (top == NULL) { 395*c99fb5f9SBaptiste Daroussin top = ucl_object_typed_new (UCL_ARRAY); 396*c99fb5f9SBaptiste Daroussin top->value.av = elt; 397*c99fb5f9SBaptiste Daroussin elt->next = NULL; 398*c99fb5f9SBaptiste Daroussin elt->prev = elt; 399*c99fb5f9SBaptiste Daroussin top->len = 1; 400*c99fb5f9SBaptiste Daroussin } 401*c99fb5f9SBaptiste Daroussin else { 402*c99fb5f9SBaptiste Daroussin head = top->value.av; 403*c99fb5f9SBaptiste Daroussin if (head == NULL) { 404*c99fb5f9SBaptiste Daroussin top->value.av = elt; 405*c99fb5f9SBaptiste Daroussin elt->prev = elt; 406*c99fb5f9SBaptiste Daroussin } 407*c99fb5f9SBaptiste Daroussin else { 408*c99fb5f9SBaptiste Daroussin elt->prev = head->prev; 409*c99fb5f9SBaptiste Daroussin head->prev->next = elt; 410*c99fb5f9SBaptiste Daroussin head->prev = elt; 411*c99fb5f9SBaptiste Daroussin } 412*c99fb5f9SBaptiste Daroussin elt->next = NULL; 413*c99fb5f9SBaptiste Daroussin top->len ++; 414*c99fb5f9SBaptiste Daroussin } 415*c99fb5f9SBaptiste Daroussin 416*c99fb5f9SBaptiste Daroussin return top; 417*c99fb5f9SBaptiste Daroussin } 418*c99fb5f9SBaptiste Daroussin 419*c99fb5f9SBaptiste Daroussin /** 420*c99fb5f9SBaptiste Daroussin * Append an element to the start of array object 421*c99fb5f9SBaptiste Daroussin * @param top destination object (will be created automatically if top is NULL) 422*c99fb5f9SBaptiste Daroussin * @param elt element to append (must NOT be NULL) 423*c99fb5f9SBaptiste Daroussin * @return new value of top object 424*c99fb5f9SBaptiste Daroussin */ 425*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * ucl_array_prepend (ucl_object_t *top, 426*c99fb5f9SBaptiste Daroussin ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; 427*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 428*c99fb5f9SBaptiste Daroussin ucl_array_prepend (ucl_object_t *top, ucl_object_t *elt) 429*c99fb5f9SBaptiste Daroussin { 430*c99fb5f9SBaptiste Daroussin ucl_object_t *head; 431*c99fb5f9SBaptiste Daroussin 432*c99fb5f9SBaptiste Daroussin if (elt == NULL) { 433*c99fb5f9SBaptiste Daroussin return NULL; 434*c99fb5f9SBaptiste Daroussin } 435*c99fb5f9SBaptiste Daroussin 436*c99fb5f9SBaptiste Daroussin if (top == NULL) { 437*c99fb5f9SBaptiste Daroussin top = ucl_object_typed_new (UCL_ARRAY); 438*c99fb5f9SBaptiste Daroussin top->value.av = elt; 439*c99fb5f9SBaptiste Daroussin elt->next = NULL; 440*c99fb5f9SBaptiste Daroussin elt->prev = elt; 441*c99fb5f9SBaptiste Daroussin top->len = 1; 442*c99fb5f9SBaptiste Daroussin } 443*c99fb5f9SBaptiste Daroussin else { 444*c99fb5f9SBaptiste Daroussin head = top->value.av; 445*c99fb5f9SBaptiste Daroussin if (head == NULL) { 446*c99fb5f9SBaptiste Daroussin top->value.av = elt; 447*c99fb5f9SBaptiste Daroussin elt->prev = elt; 448*c99fb5f9SBaptiste Daroussin } 449*c99fb5f9SBaptiste Daroussin else { 450*c99fb5f9SBaptiste Daroussin elt->prev = head->prev; 451*c99fb5f9SBaptiste Daroussin head->prev = elt; 452*c99fb5f9SBaptiste Daroussin } 453*c99fb5f9SBaptiste Daroussin elt->next = head; 454*c99fb5f9SBaptiste Daroussin top->value.av = elt; 455*c99fb5f9SBaptiste Daroussin top->len ++; 456*c99fb5f9SBaptiste Daroussin } 457*c99fb5f9SBaptiste Daroussin 458*c99fb5f9SBaptiste Daroussin return top; 459*c99fb5f9SBaptiste Daroussin } 460*c99fb5f9SBaptiste Daroussin 461*c99fb5f9SBaptiste Daroussin /** 462*c99fb5f9SBaptiste Daroussin * Removes an element `elt` from the array `top`. Caller must unref the returned object when it is not 463*c99fb5f9SBaptiste Daroussin * needed. 464*c99fb5f9SBaptiste Daroussin * @param top array ucl object 465*c99fb5f9SBaptiste Daroussin * @param elt element to remove 466*c99fb5f9SBaptiste Daroussin * @return removed element or NULL if `top` is NULL or not an array 467*c99fb5f9SBaptiste Daroussin */ 468*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 469*c99fb5f9SBaptiste Daroussin ucl_array_delete (ucl_object_t *top, ucl_object_t *elt) 470*c99fb5f9SBaptiste Daroussin { 471*c99fb5f9SBaptiste Daroussin ucl_object_t *head; 472*c99fb5f9SBaptiste Daroussin 473*c99fb5f9SBaptiste Daroussin if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 474*c99fb5f9SBaptiste Daroussin return NULL; 475*c99fb5f9SBaptiste Daroussin } 476*c99fb5f9SBaptiste Daroussin head = top->value.av; 477*c99fb5f9SBaptiste Daroussin 478*c99fb5f9SBaptiste Daroussin if (elt->prev == elt) { 479*c99fb5f9SBaptiste Daroussin top->value.av = NULL; 480*c99fb5f9SBaptiste Daroussin } 481*c99fb5f9SBaptiste Daroussin else if (elt == head) { 482*c99fb5f9SBaptiste Daroussin elt->next->prev = elt->prev; 483*c99fb5f9SBaptiste Daroussin top->value.av = elt->next; 484*c99fb5f9SBaptiste Daroussin } 485*c99fb5f9SBaptiste Daroussin else { 486*c99fb5f9SBaptiste Daroussin elt->prev->next = elt->next; 487*c99fb5f9SBaptiste Daroussin if (elt->next) { 488*c99fb5f9SBaptiste Daroussin elt->next->prev = elt->prev; 489*c99fb5f9SBaptiste Daroussin } 490*c99fb5f9SBaptiste Daroussin else { 491*c99fb5f9SBaptiste Daroussin head->prev = elt->prev; 492*c99fb5f9SBaptiste Daroussin } 493*c99fb5f9SBaptiste Daroussin } 494*c99fb5f9SBaptiste Daroussin elt->next = NULL; 495*c99fb5f9SBaptiste Daroussin elt->prev = elt; 496*c99fb5f9SBaptiste Daroussin top->len --; 497*c99fb5f9SBaptiste Daroussin 498*c99fb5f9SBaptiste Daroussin return elt; 499*c99fb5f9SBaptiste Daroussin } 500*c99fb5f9SBaptiste Daroussin 501*c99fb5f9SBaptiste Daroussin /** 502*c99fb5f9SBaptiste Daroussin * Returns the first element of the array `top` 503*c99fb5f9SBaptiste Daroussin * @param top array ucl object 504*c99fb5f9SBaptiste Daroussin * @return element or NULL if `top` is NULL or not an array 505*c99fb5f9SBaptiste Daroussin */ 506*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 507*c99fb5f9SBaptiste Daroussin ucl_array_head (ucl_object_t *top) 508*c99fb5f9SBaptiste Daroussin { 509*c99fb5f9SBaptiste Daroussin if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 510*c99fb5f9SBaptiste Daroussin return NULL; 511*c99fb5f9SBaptiste Daroussin } 512*c99fb5f9SBaptiste Daroussin return top->value.av; 513*c99fb5f9SBaptiste Daroussin } 514*c99fb5f9SBaptiste Daroussin 515*c99fb5f9SBaptiste Daroussin /** 516*c99fb5f9SBaptiste Daroussin * Returns the last element of the array `top` 517*c99fb5f9SBaptiste Daroussin * @param top array ucl object 518*c99fb5f9SBaptiste Daroussin * @return element or NULL if `top` is NULL or not an array 519*c99fb5f9SBaptiste Daroussin */ 520*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 521*c99fb5f9SBaptiste Daroussin ucl_array_tail (ucl_object_t *top) 522*c99fb5f9SBaptiste Daroussin { 523*c99fb5f9SBaptiste Daroussin if (top == NULL || top->type != UCL_ARRAY || top->value.av == NULL) { 524*c99fb5f9SBaptiste Daroussin return NULL; 525*c99fb5f9SBaptiste Daroussin } 526*c99fb5f9SBaptiste Daroussin return top->value.av->prev; 527*c99fb5f9SBaptiste Daroussin } 528*c99fb5f9SBaptiste Daroussin 529*c99fb5f9SBaptiste Daroussin /** 530*c99fb5f9SBaptiste Daroussin * Removes the last element from the array `top`. Caller must unref the returned object when it is not 531*c99fb5f9SBaptiste Daroussin * needed. 532*c99fb5f9SBaptiste Daroussin * @param top array ucl object 533*c99fb5f9SBaptiste Daroussin * @return removed element or NULL if `top` is NULL or not an array 534*c99fb5f9SBaptiste Daroussin */ 535*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 536*c99fb5f9SBaptiste Daroussin ucl_array_pop_last (ucl_object_t *top) 537*c99fb5f9SBaptiste Daroussin { 538*c99fb5f9SBaptiste Daroussin return ucl_array_delete (top, ucl_array_tail (top)); 539*c99fb5f9SBaptiste Daroussin } 540*c99fb5f9SBaptiste Daroussin 541*c99fb5f9SBaptiste Daroussin /** 542*c99fb5f9SBaptiste Daroussin * Removes the first element from the array `top`. Caller must unref the returned object when it is not 543*c99fb5f9SBaptiste Daroussin * needed. 544*c99fb5f9SBaptiste Daroussin * @param top array ucl object 545*c99fb5f9SBaptiste Daroussin * @return removed element or NULL if `top` is NULL or not an array 546*c99fb5f9SBaptiste Daroussin */ 547*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 548*c99fb5f9SBaptiste Daroussin ucl_array_pop_first (ucl_object_t *top) 549*c99fb5f9SBaptiste Daroussin { 550*c99fb5f9SBaptiste Daroussin return ucl_array_delete (top, ucl_array_head (top)); 551*c99fb5f9SBaptiste Daroussin } 552*c99fb5f9SBaptiste Daroussin 553*c99fb5f9SBaptiste Daroussin /** 554*c99fb5f9SBaptiste Daroussin * Append a element to another element forming an implicit array 555*c99fb5f9SBaptiste Daroussin * @param head head to append (may be NULL) 556*c99fb5f9SBaptiste Daroussin * @param elt new element 557*c99fb5f9SBaptiste Daroussin * @return new head if applicable 558*c99fb5f9SBaptiste Daroussin */ 559*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * ucl_elt_append (ucl_object_t *head, 560*c99fb5f9SBaptiste Daroussin ucl_object_t *elt) UCL_WARN_UNUSED_RESULT; 561*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 562*c99fb5f9SBaptiste Daroussin ucl_elt_append (ucl_object_t *head, ucl_object_t *elt) 563*c99fb5f9SBaptiste Daroussin { 564*c99fb5f9SBaptiste Daroussin 565*c99fb5f9SBaptiste Daroussin if (head == NULL) { 566*c99fb5f9SBaptiste Daroussin elt->next = NULL; 567*c99fb5f9SBaptiste Daroussin elt->prev = elt; 568*c99fb5f9SBaptiste Daroussin head = elt; 569*c99fb5f9SBaptiste Daroussin } 570*c99fb5f9SBaptiste Daroussin else { 571*c99fb5f9SBaptiste Daroussin elt->prev = head->prev; 572*c99fb5f9SBaptiste Daroussin head->prev->next = elt; 573*c99fb5f9SBaptiste Daroussin head->prev = elt; 574*c99fb5f9SBaptiste Daroussin elt->next = NULL; 575*c99fb5f9SBaptiste Daroussin } 576*c99fb5f9SBaptiste Daroussin 577*c99fb5f9SBaptiste Daroussin return head; 578*c99fb5f9SBaptiste Daroussin } 579*c99fb5f9SBaptiste Daroussin 580*c99fb5f9SBaptiste Daroussin /** 581*c99fb5f9SBaptiste Daroussin * Converts an object to double value 582*c99fb5f9SBaptiste Daroussin * @param obj CL object 583*c99fb5f9SBaptiste Daroussin * @param target target double variable 584*c99fb5f9SBaptiste Daroussin * @return true if conversion was successful 585*c99fb5f9SBaptiste Daroussin */ 586*c99fb5f9SBaptiste Daroussin static inline bool 587*c99fb5f9SBaptiste Daroussin ucl_object_todouble_safe (ucl_object_t *obj, double *target) 588*c99fb5f9SBaptiste Daroussin { 589*c99fb5f9SBaptiste Daroussin if (obj == NULL) { 590*c99fb5f9SBaptiste Daroussin return false; 591*c99fb5f9SBaptiste Daroussin } 592*c99fb5f9SBaptiste Daroussin switch (obj->type) { 593*c99fb5f9SBaptiste Daroussin case UCL_INT: 594*c99fb5f9SBaptiste Daroussin *target = obj->value.iv; /* Probaly could cause overflow */ 595*c99fb5f9SBaptiste Daroussin break; 596*c99fb5f9SBaptiste Daroussin case UCL_FLOAT: 597*c99fb5f9SBaptiste Daroussin case UCL_TIME: 598*c99fb5f9SBaptiste Daroussin *target = obj->value.dv; 599*c99fb5f9SBaptiste Daroussin break; 600*c99fb5f9SBaptiste Daroussin default: 601*c99fb5f9SBaptiste Daroussin return false; 602*c99fb5f9SBaptiste Daroussin } 603*c99fb5f9SBaptiste Daroussin 604*c99fb5f9SBaptiste Daroussin return true; 605*c99fb5f9SBaptiste Daroussin } 606*c99fb5f9SBaptiste Daroussin 607*c99fb5f9SBaptiste Daroussin /** 608*c99fb5f9SBaptiste Daroussin * Unsafe version of \ref ucl_obj_todouble_safe 609*c99fb5f9SBaptiste Daroussin * @param obj CL object 610*c99fb5f9SBaptiste Daroussin * @return double value 611*c99fb5f9SBaptiste Daroussin */ 612*c99fb5f9SBaptiste Daroussin static inline double 613*c99fb5f9SBaptiste Daroussin ucl_object_todouble (ucl_object_t *obj) 614*c99fb5f9SBaptiste Daroussin { 615*c99fb5f9SBaptiste Daroussin double result = 0.; 616*c99fb5f9SBaptiste Daroussin 617*c99fb5f9SBaptiste Daroussin ucl_object_todouble_safe (obj, &result); 618*c99fb5f9SBaptiste Daroussin return result; 619*c99fb5f9SBaptiste Daroussin } 620*c99fb5f9SBaptiste Daroussin 621*c99fb5f9SBaptiste Daroussin /** 622*c99fb5f9SBaptiste Daroussin * Converts an object to integer value 623*c99fb5f9SBaptiste Daroussin * @param obj CL object 624*c99fb5f9SBaptiste Daroussin * @param target target integer variable 625*c99fb5f9SBaptiste Daroussin * @return true if conversion was successful 626*c99fb5f9SBaptiste Daroussin */ 627*c99fb5f9SBaptiste Daroussin static inline bool 628*c99fb5f9SBaptiste Daroussin ucl_object_toint_safe (ucl_object_t *obj, int64_t *target) 629*c99fb5f9SBaptiste Daroussin { 630*c99fb5f9SBaptiste Daroussin if (obj == NULL) { 631*c99fb5f9SBaptiste Daroussin return false; 632*c99fb5f9SBaptiste Daroussin } 633*c99fb5f9SBaptiste Daroussin switch (obj->type) { 634*c99fb5f9SBaptiste Daroussin case UCL_INT: 635*c99fb5f9SBaptiste Daroussin *target = obj->value.iv; 636*c99fb5f9SBaptiste Daroussin break; 637*c99fb5f9SBaptiste Daroussin case UCL_FLOAT: 638*c99fb5f9SBaptiste Daroussin case UCL_TIME: 639*c99fb5f9SBaptiste Daroussin *target = obj->value.dv; /* Loosing of decimal points */ 640*c99fb5f9SBaptiste Daroussin break; 641*c99fb5f9SBaptiste Daroussin default: 642*c99fb5f9SBaptiste Daroussin return false; 643*c99fb5f9SBaptiste Daroussin } 644*c99fb5f9SBaptiste Daroussin 645*c99fb5f9SBaptiste Daroussin return true; 646*c99fb5f9SBaptiste Daroussin } 647*c99fb5f9SBaptiste Daroussin 648*c99fb5f9SBaptiste Daroussin /** 649*c99fb5f9SBaptiste Daroussin * Unsafe version of \ref ucl_obj_toint_safe 650*c99fb5f9SBaptiste Daroussin * @param obj CL object 651*c99fb5f9SBaptiste Daroussin * @return int value 652*c99fb5f9SBaptiste Daroussin */ 653*c99fb5f9SBaptiste Daroussin static inline int64_t 654*c99fb5f9SBaptiste Daroussin ucl_object_toint (ucl_object_t *obj) 655*c99fb5f9SBaptiste Daroussin { 656*c99fb5f9SBaptiste Daroussin int64_t result = 0; 657*c99fb5f9SBaptiste Daroussin 658*c99fb5f9SBaptiste Daroussin ucl_object_toint_safe (obj, &result); 659*c99fb5f9SBaptiste Daroussin return result; 660*c99fb5f9SBaptiste Daroussin } 661*c99fb5f9SBaptiste Daroussin 662*c99fb5f9SBaptiste Daroussin /** 663*c99fb5f9SBaptiste Daroussin * Converts an object to boolean value 664*c99fb5f9SBaptiste Daroussin * @param obj CL object 665*c99fb5f9SBaptiste Daroussin * @param target target boolean variable 666*c99fb5f9SBaptiste Daroussin * @return true if conversion was successful 667*c99fb5f9SBaptiste Daroussin */ 668*c99fb5f9SBaptiste Daroussin static inline bool 669*c99fb5f9SBaptiste Daroussin ucl_object_toboolean_safe (ucl_object_t *obj, bool *target) 670*c99fb5f9SBaptiste Daroussin { 671*c99fb5f9SBaptiste Daroussin if (obj == NULL) { 672*c99fb5f9SBaptiste Daroussin return false; 673*c99fb5f9SBaptiste Daroussin } 674*c99fb5f9SBaptiste Daroussin switch (obj->type) { 675*c99fb5f9SBaptiste Daroussin case UCL_BOOLEAN: 676*c99fb5f9SBaptiste Daroussin *target = (obj->value.iv == true); 677*c99fb5f9SBaptiste Daroussin break; 678*c99fb5f9SBaptiste Daroussin default: 679*c99fb5f9SBaptiste Daroussin return false; 680*c99fb5f9SBaptiste Daroussin } 681*c99fb5f9SBaptiste Daroussin 682*c99fb5f9SBaptiste Daroussin return true; 683*c99fb5f9SBaptiste Daroussin } 684*c99fb5f9SBaptiste Daroussin 685*c99fb5f9SBaptiste Daroussin /** 686*c99fb5f9SBaptiste Daroussin * Unsafe version of \ref ucl_obj_toboolean_safe 687*c99fb5f9SBaptiste Daroussin * @param obj CL object 688*c99fb5f9SBaptiste Daroussin * @return boolean value 689*c99fb5f9SBaptiste Daroussin */ 690*c99fb5f9SBaptiste Daroussin static inline bool 691*c99fb5f9SBaptiste Daroussin ucl_object_toboolean (ucl_object_t *obj) 692*c99fb5f9SBaptiste Daroussin { 693*c99fb5f9SBaptiste Daroussin bool result = false; 694*c99fb5f9SBaptiste Daroussin 695*c99fb5f9SBaptiste Daroussin ucl_object_toboolean_safe (obj, &result); 696*c99fb5f9SBaptiste Daroussin return result; 697*c99fb5f9SBaptiste Daroussin } 698*c99fb5f9SBaptiste Daroussin 699*c99fb5f9SBaptiste Daroussin /** 700*c99fb5f9SBaptiste Daroussin * Converts an object to string value 701*c99fb5f9SBaptiste Daroussin * @param obj CL object 702*c99fb5f9SBaptiste Daroussin * @param target target string variable, no need to free value 703*c99fb5f9SBaptiste Daroussin * @return true if conversion was successful 704*c99fb5f9SBaptiste Daroussin */ 705*c99fb5f9SBaptiste Daroussin static inline bool 706*c99fb5f9SBaptiste Daroussin ucl_object_tostring_safe (ucl_object_t *obj, const char **target) 707*c99fb5f9SBaptiste Daroussin { 708*c99fb5f9SBaptiste Daroussin if (obj == NULL) { 709*c99fb5f9SBaptiste Daroussin return false; 710*c99fb5f9SBaptiste Daroussin } 711*c99fb5f9SBaptiste Daroussin 712*c99fb5f9SBaptiste Daroussin switch (obj->type) { 713*c99fb5f9SBaptiste Daroussin case UCL_STRING: 714*c99fb5f9SBaptiste Daroussin *target = ucl_copy_value_trash (obj); 715*c99fb5f9SBaptiste Daroussin break; 716*c99fb5f9SBaptiste Daroussin default: 717*c99fb5f9SBaptiste Daroussin return false; 718*c99fb5f9SBaptiste Daroussin } 719*c99fb5f9SBaptiste Daroussin 720*c99fb5f9SBaptiste Daroussin return true; 721*c99fb5f9SBaptiste Daroussin } 722*c99fb5f9SBaptiste Daroussin 723*c99fb5f9SBaptiste Daroussin /** 724*c99fb5f9SBaptiste Daroussin * Unsafe version of \ref ucl_obj_tostring_safe 725*c99fb5f9SBaptiste Daroussin * @param obj CL object 726*c99fb5f9SBaptiste Daroussin * @return string value 727*c99fb5f9SBaptiste Daroussin */ 728*c99fb5f9SBaptiste Daroussin static inline const char * 729*c99fb5f9SBaptiste Daroussin ucl_object_tostring (ucl_object_t *obj) 730*c99fb5f9SBaptiste Daroussin { 731*c99fb5f9SBaptiste Daroussin const char *result = NULL; 732*c99fb5f9SBaptiste Daroussin 733*c99fb5f9SBaptiste Daroussin ucl_object_tostring_safe (obj, &result); 734*c99fb5f9SBaptiste Daroussin return result; 735*c99fb5f9SBaptiste Daroussin } 736*c99fb5f9SBaptiste Daroussin 737*c99fb5f9SBaptiste Daroussin /** 738*c99fb5f9SBaptiste Daroussin * Convert any object to a string in JSON notation if needed 739*c99fb5f9SBaptiste Daroussin * @param obj CL object 740*c99fb5f9SBaptiste Daroussin * @return string value 741*c99fb5f9SBaptiste Daroussin */ 742*c99fb5f9SBaptiste Daroussin static inline const char * 743*c99fb5f9SBaptiste Daroussin ucl_object_tostring_forced (ucl_object_t *obj) 744*c99fb5f9SBaptiste Daroussin { 745*c99fb5f9SBaptiste Daroussin return ucl_copy_value_trash (obj); 746*c99fb5f9SBaptiste Daroussin } 747*c99fb5f9SBaptiste Daroussin 748*c99fb5f9SBaptiste Daroussin /** 749*c99fb5f9SBaptiste Daroussin * Return string as char * and len, string may be not zero terminated, more efficient that \ref ucl_obj_tostring as it 750*c99fb5f9SBaptiste Daroussin * allows zero-copy (if #UCL_PARSER_ZEROCOPY has been used during parsing) 751*c99fb5f9SBaptiste Daroussin * @param obj CL object 752*c99fb5f9SBaptiste Daroussin * @param target target string variable, no need to free value 753*c99fb5f9SBaptiste Daroussin * @param tlen target length 754*c99fb5f9SBaptiste Daroussin * @return true if conversion was successful 755*c99fb5f9SBaptiste Daroussin */ 756*c99fb5f9SBaptiste Daroussin static inline bool 757*c99fb5f9SBaptiste Daroussin ucl_object_tolstring_safe (ucl_object_t *obj, const char **target, size_t *tlen) 758*c99fb5f9SBaptiste Daroussin { 759*c99fb5f9SBaptiste Daroussin if (obj == NULL) { 760*c99fb5f9SBaptiste Daroussin return false; 761*c99fb5f9SBaptiste Daroussin } 762*c99fb5f9SBaptiste Daroussin switch (obj->type) { 763*c99fb5f9SBaptiste Daroussin case UCL_STRING: 764*c99fb5f9SBaptiste Daroussin *target = obj->value.sv; 765*c99fb5f9SBaptiste Daroussin *tlen = obj->len; 766*c99fb5f9SBaptiste Daroussin break; 767*c99fb5f9SBaptiste Daroussin default: 768*c99fb5f9SBaptiste Daroussin return false; 769*c99fb5f9SBaptiste Daroussin } 770*c99fb5f9SBaptiste Daroussin 771*c99fb5f9SBaptiste Daroussin return true; 772*c99fb5f9SBaptiste Daroussin } 773*c99fb5f9SBaptiste Daroussin 774*c99fb5f9SBaptiste Daroussin /** 775*c99fb5f9SBaptiste Daroussin * Unsafe version of \ref ucl_obj_tolstring_safe 776*c99fb5f9SBaptiste Daroussin * @param obj CL object 777*c99fb5f9SBaptiste Daroussin * @return string value 778*c99fb5f9SBaptiste Daroussin */ 779*c99fb5f9SBaptiste Daroussin static inline const char * 780*c99fb5f9SBaptiste Daroussin ucl_object_tolstring (ucl_object_t *obj, size_t *tlen) 781*c99fb5f9SBaptiste Daroussin { 782*c99fb5f9SBaptiste Daroussin const char *result = NULL; 783*c99fb5f9SBaptiste Daroussin 784*c99fb5f9SBaptiste Daroussin ucl_object_tolstring_safe (obj, &result, tlen); 785*c99fb5f9SBaptiste Daroussin return result; 786*c99fb5f9SBaptiste Daroussin } 787*c99fb5f9SBaptiste Daroussin 788*c99fb5f9SBaptiste Daroussin /** 789*c99fb5f9SBaptiste Daroussin * Return object identified by a key in the specified object 790*c99fb5f9SBaptiste Daroussin * @param obj object to get a key from (must be of type UCL_OBJECT) 791*c99fb5f9SBaptiste Daroussin * @param key key to search 792*c99fb5f9SBaptiste Daroussin * @return object matched the specified key or NULL if key is not found 793*c99fb5f9SBaptiste Daroussin */ 794*c99fb5f9SBaptiste Daroussin ucl_object_t * ucl_object_find_key (ucl_object_t *obj, const char *key); 795*c99fb5f9SBaptiste Daroussin 796*c99fb5f9SBaptiste Daroussin /** 797*c99fb5f9SBaptiste Daroussin * Return object identified by a fixed size key in the specified object 798*c99fb5f9SBaptiste Daroussin * @param obj object to get a key from (must be of type UCL_OBJECT) 799*c99fb5f9SBaptiste Daroussin * @param key key to search 800*c99fb5f9SBaptiste Daroussin * @param klen length of a key 801*c99fb5f9SBaptiste Daroussin * @return object matched the specified key or NULL if key is not found 802*c99fb5f9SBaptiste Daroussin */ 803*c99fb5f9SBaptiste Daroussin ucl_object_t *ucl_object_find_keyl (ucl_object_t *obj, const char *key, size_t klen); 804*c99fb5f9SBaptiste Daroussin 805*c99fb5f9SBaptiste Daroussin /** 806*c99fb5f9SBaptiste Daroussin * Returns a key of an object as a NULL terminated string 807*c99fb5f9SBaptiste Daroussin * @param obj CL object 808*c99fb5f9SBaptiste Daroussin * @return key or NULL if there is no key 809*c99fb5f9SBaptiste Daroussin */ 810*c99fb5f9SBaptiste Daroussin static inline const char * 811*c99fb5f9SBaptiste Daroussin ucl_object_key (ucl_object_t *obj) 812*c99fb5f9SBaptiste Daroussin { 813*c99fb5f9SBaptiste Daroussin return ucl_copy_key_trash (obj); 814*c99fb5f9SBaptiste Daroussin } 815*c99fb5f9SBaptiste Daroussin 816*c99fb5f9SBaptiste Daroussin /** 817*c99fb5f9SBaptiste Daroussin * Returns a key of an object as a fixed size string (may be more efficient) 818*c99fb5f9SBaptiste Daroussin * @param obj CL object 819*c99fb5f9SBaptiste Daroussin * @param len target key length 820*c99fb5f9SBaptiste Daroussin * @return key pointer 821*c99fb5f9SBaptiste Daroussin */ 822*c99fb5f9SBaptiste Daroussin static inline const char * 823*c99fb5f9SBaptiste Daroussin ucl_object_keyl (ucl_object_t *obj, size_t *len) 824*c99fb5f9SBaptiste Daroussin { 825*c99fb5f9SBaptiste Daroussin *len = obj->keylen; 826*c99fb5f9SBaptiste Daroussin return obj->key; 827*c99fb5f9SBaptiste Daroussin } 828*c99fb5f9SBaptiste Daroussin 829*c99fb5f9SBaptiste Daroussin /** 830*c99fb5f9SBaptiste Daroussin * Free ucl object 831*c99fb5f9SBaptiste Daroussin * @param obj ucl object to free 832*c99fb5f9SBaptiste Daroussin */ 833*c99fb5f9SBaptiste Daroussin void ucl_object_free (ucl_object_t *obj); 834*c99fb5f9SBaptiste Daroussin 835*c99fb5f9SBaptiste Daroussin /** 836*c99fb5f9SBaptiste Daroussin * Increase reference count for an object 837*c99fb5f9SBaptiste Daroussin * @param obj object to ref 838*c99fb5f9SBaptiste Daroussin */ 839*c99fb5f9SBaptiste Daroussin static inline ucl_object_t * 840*c99fb5f9SBaptiste Daroussin ucl_object_ref (ucl_object_t *obj) { 841*c99fb5f9SBaptiste Daroussin obj->ref ++; 842*c99fb5f9SBaptiste Daroussin return obj; 843*c99fb5f9SBaptiste Daroussin } 844*c99fb5f9SBaptiste Daroussin 845*c99fb5f9SBaptiste Daroussin /** 846*c99fb5f9SBaptiste Daroussin * Decrease reference count for an object 847*c99fb5f9SBaptiste Daroussin * @param obj object to unref 848*c99fb5f9SBaptiste Daroussin */ 849*c99fb5f9SBaptiste Daroussin static inline void 850*c99fb5f9SBaptiste Daroussin ucl_object_unref (ucl_object_t *obj) { 851*c99fb5f9SBaptiste Daroussin if (obj != NULL && --obj->ref <= 0) { 852*c99fb5f9SBaptiste Daroussin ucl_object_free (obj); 853*c99fb5f9SBaptiste Daroussin } 854*c99fb5f9SBaptiste Daroussin } 855*c99fb5f9SBaptiste Daroussin /** 856*c99fb5f9SBaptiste Daroussin * Opaque iterator object 857*c99fb5f9SBaptiste Daroussin */ 858*c99fb5f9SBaptiste Daroussin typedef void* ucl_object_iter_t; 859*c99fb5f9SBaptiste Daroussin 860*c99fb5f9SBaptiste Daroussin /** 861*c99fb5f9SBaptiste Daroussin * Get next key from an object 862*c99fb5f9SBaptiste Daroussin * @param obj object to iterate 863*c99fb5f9SBaptiste Daroussin * @param iter opaque iterator, must be set to NULL on the first call: 864*c99fb5f9SBaptiste Daroussin * ucl_object_iter_t it = NULL; 865*c99fb5f9SBaptiste Daroussin * while ((cur = ucl_iterate_object (obj, &it)) != NULL) ... 866*c99fb5f9SBaptiste Daroussin * @return the next object or NULL 867*c99fb5f9SBaptiste Daroussin */ 868*c99fb5f9SBaptiste Daroussin ucl_object_t* ucl_iterate_object (ucl_object_t *obj, ucl_object_iter_t *iter, bool expand_values); 869*c99fb5f9SBaptiste Daroussin /** @} */ 870*c99fb5f9SBaptiste Daroussin 871*c99fb5f9SBaptiste Daroussin 872*c99fb5f9SBaptiste Daroussin /** 873*c99fb5f9SBaptiste Daroussin * @defgroup parser Parsing functions 874*c99fb5f9SBaptiste Daroussin * These functions are used to parse UCL objects 875*c99fb5f9SBaptiste Daroussin * 876*c99fb5f9SBaptiste Daroussin * @{ 877*c99fb5f9SBaptiste Daroussin */ 878*c99fb5f9SBaptiste Daroussin 879*c99fb5f9SBaptiste Daroussin /** 880*c99fb5f9SBaptiste Daroussin * Macro handler for a parser 881*c99fb5f9SBaptiste Daroussin * @param data the content of macro 882*c99fb5f9SBaptiste Daroussin * @param len the length of content 883*c99fb5f9SBaptiste Daroussin * @param ud opaque user data 884*c99fb5f9SBaptiste Daroussin * @param err error pointer 885*c99fb5f9SBaptiste Daroussin * @return true if macro has been parsed 886*c99fb5f9SBaptiste Daroussin */ 887*c99fb5f9SBaptiste Daroussin typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud); 888*c99fb5f9SBaptiste Daroussin 889*c99fb5f9SBaptiste Daroussin /* Opaque parser */ 890*c99fb5f9SBaptiste Daroussin struct ucl_parser; 891*c99fb5f9SBaptiste Daroussin 892*c99fb5f9SBaptiste Daroussin /** 893*c99fb5f9SBaptiste Daroussin * Creates new parser object 894*c99fb5f9SBaptiste Daroussin * @param pool pool to allocate memory from 895*c99fb5f9SBaptiste Daroussin * @return new parser object 896*c99fb5f9SBaptiste Daroussin */ 897*c99fb5f9SBaptiste Daroussin struct ucl_parser* ucl_parser_new (int flags); 898*c99fb5f9SBaptiste Daroussin 899*c99fb5f9SBaptiste Daroussin /** 900*c99fb5f9SBaptiste Daroussin * Register new handler for a macro 901*c99fb5f9SBaptiste Daroussin * @param parser parser object 902*c99fb5f9SBaptiste Daroussin * @param macro macro name (without leading dot) 903*c99fb5f9SBaptiste Daroussin * @param handler handler (it is called immediately after macro is parsed) 904*c99fb5f9SBaptiste Daroussin * @param ud opaque user data for a handler 905*c99fb5f9SBaptiste Daroussin */ 906*c99fb5f9SBaptiste Daroussin void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, 907*c99fb5f9SBaptiste Daroussin ucl_macro_handler handler, void* ud); 908*c99fb5f9SBaptiste Daroussin 909*c99fb5f9SBaptiste Daroussin /** 910*c99fb5f9SBaptiste Daroussin * Register new parser variable 911*c99fb5f9SBaptiste Daroussin * @param parser parser object 912*c99fb5f9SBaptiste Daroussin * @param var variable name 913*c99fb5f9SBaptiste Daroussin * @param value variable value 914*c99fb5f9SBaptiste Daroussin */ 915*c99fb5f9SBaptiste Daroussin void ucl_parser_register_variable (struct ucl_parser *parser, const char *var, 916*c99fb5f9SBaptiste Daroussin const char *value); 917*c99fb5f9SBaptiste Daroussin 918*c99fb5f9SBaptiste Daroussin /** 919*c99fb5f9SBaptiste Daroussin * Load new chunk to a parser 920*c99fb5f9SBaptiste Daroussin * @param parser parser structure 921*c99fb5f9SBaptiste Daroussin * @param data the pointer to the beginning of a chunk 922*c99fb5f9SBaptiste Daroussin * @param len the length of a chunk 923*c99fb5f9SBaptiste Daroussin * @param err if *err is NULL it is set to parser error 924*c99fb5f9SBaptiste Daroussin * @return true if chunk has been added and false in case of error 925*c99fb5f9SBaptiste Daroussin */ 926*c99fb5f9SBaptiste Daroussin bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len); 927*c99fb5f9SBaptiste Daroussin 928*c99fb5f9SBaptiste Daroussin /** 929*c99fb5f9SBaptiste Daroussin * Load and add data from a file 930*c99fb5f9SBaptiste Daroussin * @param parser parser structure 931*c99fb5f9SBaptiste Daroussin * @param filename the name of file 932*c99fb5f9SBaptiste Daroussin * @param err if *err is NULL it is set to parser error 933*c99fb5f9SBaptiste Daroussin * @return true if chunk has been added and false in case of error 934*c99fb5f9SBaptiste Daroussin */ 935*c99fb5f9SBaptiste Daroussin bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename); 936*c99fb5f9SBaptiste Daroussin 937*c99fb5f9SBaptiste Daroussin /** 938*c99fb5f9SBaptiste Daroussin * Get a top object for a parser 939*c99fb5f9SBaptiste Daroussin * @param parser parser structure 940*c99fb5f9SBaptiste Daroussin * @param err if *err is NULL it is set to parser error 941*c99fb5f9SBaptiste Daroussin * @return top parser object or NULL 942*c99fb5f9SBaptiste Daroussin */ 943*c99fb5f9SBaptiste Daroussin ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); 944*c99fb5f9SBaptiste Daroussin 945*c99fb5f9SBaptiste Daroussin /** 946*c99fb5f9SBaptiste Daroussin * Get the error string if failing 947*c99fb5f9SBaptiste Daroussin * @param parser parser object 948*c99fb5f9SBaptiste Daroussin */ 949*c99fb5f9SBaptiste Daroussin const char *ucl_parser_get_error(struct ucl_parser *parser); 950*c99fb5f9SBaptiste Daroussin /** 951*c99fb5f9SBaptiste Daroussin * Free ucl parser object 952*c99fb5f9SBaptiste Daroussin * @param parser parser object 953*c99fb5f9SBaptiste Daroussin */ 954*c99fb5f9SBaptiste Daroussin void ucl_parser_free (struct ucl_parser *parser); 955*c99fb5f9SBaptiste Daroussin 956*c99fb5f9SBaptiste Daroussin /** 957*c99fb5f9SBaptiste Daroussin * Add new public key to parser for signatures check 958*c99fb5f9SBaptiste Daroussin * @param parser parser object 959*c99fb5f9SBaptiste Daroussin * @param key PEM representation of a key 960*c99fb5f9SBaptiste Daroussin * @param len length of the key 961*c99fb5f9SBaptiste Daroussin * @param err if *err is NULL it is set to parser error 962*c99fb5f9SBaptiste Daroussin * @return true if a key has been successfully added 963*c99fb5f9SBaptiste Daroussin */ 964*c99fb5f9SBaptiste Daroussin bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len); 965*c99fb5f9SBaptiste Daroussin 966*c99fb5f9SBaptiste Daroussin /** 967*c99fb5f9SBaptiste Daroussin * Set FILENAME and CURDIR variables in parser 968*c99fb5f9SBaptiste Daroussin * @param parser parser object 969*c99fb5f9SBaptiste Daroussin * @param filename filename to set or NULL to set FILENAME to "undef" and CURDIR to getcwd() 970*c99fb5f9SBaptiste Daroussin * @param need_expand perform realpath() if this variable is true and filename is not NULL 971*c99fb5f9SBaptiste Daroussin * @return true if variables has been set 972*c99fb5f9SBaptiste Daroussin */ 973*c99fb5f9SBaptiste Daroussin bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, 974*c99fb5f9SBaptiste Daroussin bool need_expand); 975*c99fb5f9SBaptiste Daroussin 976*c99fb5f9SBaptiste Daroussin /** @} */ 977*c99fb5f9SBaptiste Daroussin 978*c99fb5f9SBaptiste Daroussin /** 979*c99fb5f9SBaptiste Daroussin * @defgroup emitter Emitting functions 980*c99fb5f9SBaptiste Daroussin * These functions are used to serialise UCL objects to some string representation. 981*c99fb5f9SBaptiste Daroussin * 982*c99fb5f9SBaptiste Daroussin * @{ 983*c99fb5f9SBaptiste Daroussin */ 984*c99fb5f9SBaptiste Daroussin 985*c99fb5f9SBaptiste Daroussin /** 986*c99fb5f9SBaptiste Daroussin * Structure using for emitter callbacks 987*c99fb5f9SBaptiste Daroussin */ 988*c99fb5f9SBaptiste Daroussin struct ucl_emitter_functions { 989*c99fb5f9SBaptiste Daroussin /** Append a single character */ 990*c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_character) (unsigned char c, size_t nchars, void *ud); 991*c99fb5f9SBaptiste Daroussin /** Append a string of a specified length */ 992*c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_len) (unsigned const char *str, size_t len, void *ud); 993*c99fb5f9SBaptiste Daroussin /** Append a 64 bit integer */ 994*c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_int) (int64_t elt, void *ud); 995*c99fb5f9SBaptiste Daroussin /** Append floating point element */ 996*c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_double) (double elt, void *ud); 997*c99fb5f9SBaptiste Daroussin /** Opaque userdata pointer */ 998*c99fb5f9SBaptiste Daroussin void *ud; 999*c99fb5f9SBaptiste Daroussin }; 1000*c99fb5f9SBaptiste Daroussin 1001*c99fb5f9SBaptiste Daroussin /** 1002*c99fb5f9SBaptiste Daroussin * Emit object to a string 1003*c99fb5f9SBaptiste Daroussin * @param obj object 1004*c99fb5f9SBaptiste Daroussin * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is 1005*c99fb5f9SBaptiste Daroussin * #UCL_EMIT_CONFIG then emit config like object 1006*c99fb5f9SBaptiste Daroussin * @return dump of an object (must be freed after using) or NULL in case of error 1007*c99fb5f9SBaptiste Daroussin */ 1008*c99fb5f9SBaptiste Daroussin unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); 1009*c99fb5f9SBaptiste Daroussin 1010*c99fb5f9SBaptiste Daroussin /** 1011*c99fb5f9SBaptiste Daroussin * Emit object to a string 1012*c99fb5f9SBaptiste Daroussin * @param obj object 1013*c99fb5f9SBaptiste Daroussin * @param emit_type if type is #UCL_EMIT_JSON then emit json, if type is 1014*c99fb5f9SBaptiste Daroussin * #UCL_EMIT_CONFIG then emit config like object 1015*c99fb5f9SBaptiste Daroussin * @return dump of an object (must be freed after using) or NULL in case of error 1016*c99fb5f9SBaptiste Daroussin */ 1017*c99fb5f9SBaptiste Daroussin bool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, 1018*c99fb5f9SBaptiste Daroussin struct ucl_emitter_functions *emitter); 1019*c99fb5f9SBaptiste Daroussin /** @} */ 1020*c99fb5f9SBaptiste Daroussin 1021*c99fb5f9SBaptiste Daroussin #ifdef __cplusplus 1022*c99fb5f9SBaptiste Daroussin } 1023*c99fb5f9SBaptiste Daroussin #endif 1024*c99fb5f9SBaptiste Daroussin /* 1025*c99fb5f9SBaptiste Daroussin * XXX: Poorly named API functions, need to replace them with the appropriate 1026*c99fb5f9SBaptiste Daroussin * named function. All API functions *must* use naming ucl_object_*. Usage of 1027*c99fb5f9SBaptiste Daroussin * ucl_obj* should be avoided. 1028*c99fb5f9SBaptiste Daroussin */ 1029*c99fb5f9SBaptiste Daroussin #define ucl_obj_todouble_safe ucl_object_todouble_safe 1030*c99fb5f9SBaptiste Daroussin #define ucl_obj_todouble ucl_object_todouble 1031*c99fb5f9SBaptiste Daroussin #define ucl_obj_tostring ucl_object_tostring 1032*c99fb5f9SBaptiste Daroussin #define ucl_obj_tostring_safe ucl_object_tostring_safe 1033*c99fb5f9SBaptiste Daroussin #define ucl_obj_tolstring ucl_object_tolstring 1034*c99fb5f9SBaptiste Daroussin #define ucl_obj_tolstring_safe ucl_object_tolstring_safe 1035*c99fb5f9SBaptiste Daroussin #define ucl_obj_toint ucl_object_toint 1036*c99fb5f9SBaptiste Daroussin #define ucl_obj_toint_safe ucl_object_toint_safe 1037*c99fb5f9SBaptiste Daroussin #define ucl_obj_toboolean ucl_object_toboolean 1038*c99fb5f9SBaptiste Daroussin #define ucl_obj_toboolean_safe ucl_object_toboolean_safe 1039*c99fb5f9SBaptiste Daroussin #define ucl_obj_get_key ucl_object_find_key 1040*c99fb5f9SBaptiste Daroussin #define ucl_obj_get_keyl ucl_object_find_keyl 1041*c99fb5f9SBaptiste Daroussin #define ucl_obj_unref ucl_object_unref 1042*c99fb5f9SBaptiste Daroussin #define ucl_obj_ref ucl_object_ref 1043*c99fb5f9SBaptiste Daroussin #define ucl_obj_free ucl_object_free 1044*c99fb5f9SBaptiste Daroussin 1045*c99fb5f9SBaptiste Daroussin #endif /* UCL_H_ */ 1046