1*c99fb5f9SBaptiste DaroussinSynopsis 2*c99fb5f9SBaptiste Daroussin======== 3*c99fb5f9SBaptiste Daroussin 4*c99fb5f9SBaptiste Daroussin`#include <ucl.h>` 5*c99fb5f9SBaptiste Daroussin 6*c99fb5f9SBaptiste DaroussinDescription 7*c99fb5f9SBaptiste Daroussin=========== 8*c99fb5f9SBaptiste Daroussin 9*c99fb5f9SBaptiste DaroussinLibucl is a parser and `C` API to parse and generate `ucl` objects. Libucl consist of several groups of functions: 10*c99fb5f9SBaptiste Daroussin 11*c99fb5f9SBaptiste Daroussin### Parser functions 12*c99fb5f9SBaptiste DaroussinUsed to parse `ucl` files and provide interface to extract `ucl` object 13*c99fb5f9SBaptiste Daroussin 14*c99fb5f9SBaptiste Daroussin### Emitting functions 15*c99fb5f9SBaptiste DaroussinConvert `ucl` objects to some textual or binary representation. 16*c99fb5f9SBaptiste Daroussin 17*c99fb5f9SBaptiste Daroussin### Conversion functions 18*c99fb5f9SBaptiste DaroussinHelp to convert `ucl` objects to C types 19*c99fb5f9SBaptiste Daroussin 20*c99fb5f9SBaptiste Daroussin### Generation functions 21*c99fb5f9SBaptiste DaroussinAllow creating of `ucl` objects from C types 22*c99fb5f9SBaptiste Daroussin 23*c99fb5f9SBaptiste Daroussin### Iteration functions 24*c99fb5f9SBaptiste DaroussinIterate over `ucl` objects 25*c99fb5f9SBaptiste Daroussin 26*c99fb5f9SBaptiste Daroussin### Utility functions 27*c99fb5f9SBaptiste DaroussinProvide basic utilities to manage `ucl` objects 28*c99fb5f9SBaptiste Daroussin 29*c99fb5f9SBaptiste Daroussin# Parser functions 30*c99fb5f9SBaptiste Daroussin 31*c99fb5f9SBaptiste DaroussinParser functions operates with `struct ucl_parser`. 32*c99fb5f9SBaptiste Daroussin 33*c99fb5f9SBaptiste Daroussin### ucl_parser_new 34*c99fb5f9SBaptiste Daroussin 35*c99fb5f9SBaptiste Daroussin~~~C 36*c99fb5f9SBaptiste Daroussinstruct ucl_parser* ucl_parser_new (int flags); 37*c99fb5f9SBaptiste Daroussin~~~ 38*c99fb5f9SBaptiste Daroussin 39*c99fb5f9SBaptiste DaroussinCreates new parser with the specified flags: 40*c99fb5f9SBaptiste Daroussin 41*c99fb5f9SBaptiste Daroussin- `UCL_PARSER_KEY_LOWERCASE` - lowercase keys parsed 42*c99fb5f9SBaptiste Daroussin- `UCL_PARSER_ZEROCOPY` - try to use zero-copy mode when reading files (in zero-copy mode text chunk being parsed without copying strings so it should exist till any object parsed is used) 43*c99fb5f9SBaptiste Daroussin 44*c99fb5f9SBaptiste Daroussin### ucl_parser_register_macro 45*c99fb5f9SBaptiste Daroussin 46*c99fb5f9SBaptiste Daroussin~~~C 47*c99fb5f9SBaptiste Daroussinvoid ucl_parser_register_macro (struct ucl_parser *parser, 48*c99fb5f9SBaptiste Daroussin const char *macro, ucl_macro_handler handler, void* ud); 49*c99fb5f9SBaptiste Daroussin~~~ 50*c99fb5f9SBaptiste Daroussin 51*c99fb5f9SBaptiste DaroussinRegister new macro with name .`macro` parsed by handler `handler` that accepts opaque data pointer `ud`. Macro handler should be of the following type: 52*c99fb5f9SBaptiste Daroussin 53*c99fb5f9SBaptiste Daroussin~~~C 54*c99fb5f9SBaptiste Daroussinbool (*ucl_macro_handler) (const unsigned char *data, 55*c99fb5f9SBaptiste Daroussin size_t len, void* ud);` 56*c99fb5f9SBaptiste Daroussin~~~ 57*c99fb5f9SBaptiste Daroussin 58*c99fb5f9SBaptiste DaroussinHandler function accepts macro text `data` of length `len` and the opaque pointer `ud`. If macro is parsed successfully the handler should return `true`. `false` indicates parsing failure and the parser can be terminated. 59*c99fb5f9SBaptiste Daroussin 60*c99fb5f9SBaptiste Daroussin### ucl_parser_register_variable 61*c99fb5f9SBaptiste Daroussin 62*c99fb5f9SBaptiste Daroussin~~~C 63*c99fb5f9SBaptiste Daroussinvoid ucl_parser_register_variable (struct ucl_parser *parser, 64*c99fb5f9SBaptiste Daroussin const char *var, const char *value); 65*c99fb5f9SBaptiste Daroussin~~~ 66*c99fb5f9SBaptiste Daroussin 67*c99fb5f9SBaptiste DaroussinRegister new variable $`var` that should be replaced by the parser to the `value` string. 68*c99fb5f9SBaptiste Daroussin 69*c99fb5f9SBaptiste Daroussin### ucl_parser_add_chunk 70*c99fb5f9SBaptiste Daroussin 71*c99fb5f9SBaptiste Daroussin~~~C 72*c99fb5f9SBaptiste Daroussinbool ucl_parser_add_chunk (struct ucl_parser *parser, 73*c99fb5f9SBaptiste Daroussin const unsigned char *data, size_t len); 74*c99fb5f9SBaptiste Daroussin~~~ 75*c99fb5f9SBaptiste Daroussin 76*c99fb5f9SBaptiste DaroussinAdd new text chunk with `data` of length `len` to the parser. At the moment, `libucl` parser is not a streamlined parser and chunk *must* contain the *valid* ucl object. For example, this object should be valid: 77*c99fb5f9SBaptiste Daroussin 78*c99fb5f9SBaptiste Daroussin~~~json 79*c99fb5f9SBaptiste Daroussin{ "var": "value" } 80*c99fb5f9SBaptiste Daroussin~~~ 81*c99fb5f9SBaptiste Daroussin 82*c99fb5f9SBaptiste Daroussinwhile this one won't be parsed correctly: 83*c99fb5f9SBaptiste Daroussin 84*c99fb5f9SBaptiste Daroussin~~~json 85*c99fb5f9SBaptiste Daroussin{ "var": 86*c99fb5f9SBaptiste Daroussin~~~ 87*c99fb5f9SBaptiste Daroussin 88*c99fb5f9SBaptiste DaroussinThis limitation may possible be removed in future. 89*c99fb5f9SBaptiste Daroussin 90*c99fb5f9SBaptiste Daroussin### ucl_parser_add_file 91*c99fb5f9SBaptiste Daroussin 92*c99fb5f9SBaptiste Daroussin~~~C 93*c99fb5f9SBaptiste Daroussinbool ucl_parser_add_file (struct ucl_parser *parser, 94*c99fb5f9SBaptiste Daroussin const char *filename); 95*c99fb5f9SBaptiste Daroussin~~~ 96*c99fb5f9SBaptiste Daroussin 97*c99fb5f9SBaptiste DaroussinLoad file `filename` and parse it with the specified `parser`. This function uses `mmap` call to load file, therefore, it should not be `shrinked` during parsing. Otherwise, `libucl` can cause memory corruption and terminate the calling application. This function is also used by the internal handler of `include` macro, hence, this macro has the same limitation. 98*c99fb5f9SBaptiste Daroussin 99*c99fb5f9SBaptiste Daroussin### ucl_parser_get_object 100*c99fb5f9SBaptiste Daroussin 101*c99fb5f9SBaptiste Daroussin~~~C 102*c99fb5f9SBaptiste Daroussinucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); 103*c99fb5f9SBaptiste Daroussin~~~ 104*c99fb5f9SBaptiste Daroussin 105*c99fb5f9SBaptiste DaroussinIf the `ucl` data has been parsed correctly this function returns the top object for the parser. Otherwise, this function returns the `NULL` pointer. The reference count for `ucl` object returned is increased by one, therefore, a caller should decrease reference by using `ucl_object_unref` to free object after usage. 106*c99fb5f9SBaptiste Daroussin 107*c99fb5f9SBaptiste Daroussin### ucl_parser_get_error 108*c99fb5f9SBaptiste Daroussin 109*c99fb5f9SBaptiste Daroussin~~~C 110*c99fb5f9SBaptiste Daroussinconst char *ucl_parser_get_error(struct ucl_parser *parser); 111*c99fb5f9SBaptiste Daroussin~~~ 112*c99fb5f9SBaptiste Daroussin 113*c99fb5f9SBaptiste DaroussinReturns the constant error string for the parser object. If no error occurred during parsing a `NULL` object is returned. A caller should not try to free or modify this string. 114*c99fb5f9SBaptiste Daroussin 115*c99fb5f9SBaptiste Daroussin### ucl_parser_free 116*c99fb5f9SBaptiste Daroussin 117*c99fb5f9SBaptiste Daroussin~~~C 118*c99fb5f9SBaptiste Daroussinvoid ucl_parser_free (struct ucl_parser *parser); 119*c99fb5f9SBaptiste Daroussin~~~ 120*c99fb5f9SBaptiste Daroussin 121*c99fb5f9SBaptiste DaroussinFrees memory occupied by the parser object. The reference count for top object is decreased as well, however if the function `ucl_parser_get_object` was called previously then the top object won't be freed. 122*c99fb5f9SBaptiste Daroussin 123*c99fb5f9SBaptiste Daroussin### ucl_pubkey_add 124*c99fb5f9SBaptiste Daroussin 125*c99fb5f9SBaptiste Daroussin~~~C 126*c99fb5f9SBaptiste Daroussinbool ucl_pubkey_add (struct ucl_parser *parser, 127*c99fb5f9SBaptiste Daroussin const unsigned char *key, size_t len); 128*c99fb5f9SBaptiste Daroussin~~~ 129*c99fb5f9SBaptiste Daroussin 130*c99fb5f9SBaptiste DaroussinThis function adds a public key from text blob `key` of length `len` to the `parser` object. This public key should be in the `PEM` format and can be used by `.includes` macro for checking signatures of files included. `Openssl` support should be enabled to make this function working. If a key cannot be added (e.g. due to format error) or `openssl` was not linked to `libucl` then this function returns `false`. 131*c99fb5f9SBaptiste Daroussin 132*c99fb5f9SBaptiste Daroussin### ucl_parser_set_filevars 133*c99fb5f9SBaptiste Daroussin 134*c99fb5f9SBaptiste Daroussin~~~C 135*c99fb5f9SBaptiste Daroussinbool ucl_parser_set_filevars (struct ucl_parser *parser, 136*c99fb5f9SBaptiste Daroussin const char *filename, bool need_expand); 137*c99fb5f9SBaptiste Daroussin~~~ 138*c99fb5f9SBaptiste Daroussin 139*c99fb5f9SBaptiste DaroussinAdd the standard file variables to the `parser` based on the `filename` specified: 140*c99fb5f9SBaptiste Daroussin 141*c99fb5f9SBaptiste Daroussin- `$FILENAME` - a filename of `ucl` input 142*c99fb5f9SBaptiste Daroussin- `$CURDIR` - a current directory of the input 143*c99fb5f9SBaptiste Daroussin 144*c99fb5f9SBaptiste DaroussinFor example, if a `filename` param is `../something.conf` then the variables will have the following values: 145*c99fb5f9SBaptiste Daroussin 146*c99fb5f9SBaptiste Daroussin- `$FILENAME` - "../something.conf" 147*c99fb5f9SBaptiste Daroussin- `$CURDIR` - ".." 148*c99fb5f9SBaptiste Daroussin 149*c99fb5f9SBaptiste Daroussinif `need_expand` parameter is `true` then all relative paths are expanded using `realpath` call. In this example if `..` is `/etc/dir` then variables will have these values: 150*c99fb5f9SBaptiste Daroussin 151*c99fb5f9SBaptiste Daroussin- `$FILENAME` - "/etc/something.conf" 152*c99fb5f9SBaptiste Daroussin- `$CURDIR` - "/etc" 153*c99fb5f9SBaptiste Daroussin 154*c99fb5f9SBaptiste Daroussin## Parser usage example 155*c99fb5f9SBaptiste Daroussin 156*c99fb5f9SBaptiste DaroussinThe following example loads, parses and extracts `ucl` object from stdin using `libucl` parser functions (the length of input is limited to 8K): 157*c99fb5f9SBaptiste Daroussin 158*c99fb5f9SBaptiste Daroussin~~~C 159*c99fb5f9SBaptiste Daroussinchar inbuf[8192]; 160*c99fb5f9SBaptiste Daroussinstruct ucl_parser *parser = NULL; 161*c99fb5f9SBaptiste Daroussinint ret = 0, r = 0; 162*c99fb5f9SBaptiste Daroussinucl_object_t *obj = NULL; 163*c99fb5f9SBaptiste DaroussinFILE *in; 164*c99fb5f9SBaptiste Daroussin 165*c99fb5f9SBaptiste Daroussinin = stdin; 166*c99fb5f9SBaptiste Daroussinparser = ucl_parser_new (0); 167*c99fb5f9SBaptiste Daroussinwhile (!feof (in) && r < (int)sizeof (inbuf)) { 168*c99fb5f9SBaptiste Daroussin r += fread (inbuf + r, 1, sizeof (inbuf) - r, in); 169*c99fb5f9SBaptiste Daroussin} 170*c99fb5f9SBaptiste Daroussinucl_parser_add_chunk (parser, inbuf, r); 171*c99fb5f9SBaptiste Daroussinfclose (in); 172*c99fb5f9SBaptiste Daroussin 173*c99fb5f9SBaptiste Daroussinif (ucl_parser_get_error (parser)) { 174*c99fb5f9SBaptiste Daroussin printf ("Error occured: %s\n", ucl_parser_get_error (parser)); 175*c99fb5f9SBaptiste Daroussin ret = 1; 176*c99fb5f9SBaptiste Daroussin} 177*c99fb5f9SBaptiste Daroussinelse { 178*c99fb5f9SBaptiste Daroussin obj = ucl_parser_get_object (parser); 179*c99fb5f9SBaptiste Daroussin} 180*c99fb5f9SBaptiste Daroussin 181*c99fb5f9SBaptiste Daroussinif (parser != NULL) { 182*c99fb5f9SBaptiste Daroussin ucl_parser_free (parser); 183*c99fb5f9SBaptiste Daroussin} 184*c99fb5f9SBaptiste Daroussinif (obj != NULL) { 185*c99fb5f9SBaptiste Daroussin ucl_object_unref (obj); 186*c99fb5f9SBaptiste Daroussin} 187*c99fb5f9SBaptiste Daroussinreturn ret; 188*c99fb5f9SBaptiste Daroussin~~~ 189*c99fb5f9SBaptiste Daroussin 190*c99fb5f9SBaptiste Daroussin# Emitting functions 191*c99fb5f9SBaptiste Daroussin 192*c99fb5f9SBaptiste DaroussinLibucl can transform UCL objects to a number of tectual formats: 193*c99fb5f9SBaptiste Daroussin 194*c99fb5f9SBaptiste Daroussin- configuration (`UCL_EMIT_CONFIG`) - nginx like human readable configuration file where implicit arrays are transformed to the duplicate keys 195*c99fb5f9SBaptiste Daroussin- compact json: `UCL_EMIT_JSON_COMPACT` - single line valid json without spaces 196*c99fb5f9SBaptiste Daroussin- formatted json: `UCL_EMIT_JSON` - pretty formatted JSON with newlines and spaces 197*c99fb5f9SBaptiste Daroussin- compact yaml: `UCL_EMIT_YAML` - compact YAML output 198*c99fb5f9SBaptiste Daroussin 199*c99fb5f9SBaptiste DaroussinMoreover, libucl API allows to select a custom set of emitting functions allowing 200*c99fb5f9SBaptiste Daroussinefficent and zero-copy output of libucl objects. Libucl uses the following structure to support this feature: 201*c99fb5f9SBaptiste Daroussin 202*c99fb5f9SBaptiste Daroussin~~~C 203*c99fb5f9SBaptiste Daroussinstruct ucl_emitter_functions { 204*c99fb5f9SBaptiste Daroussin /** Append a single character */ 205*c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_character) (unsigned char c, size_t nchars, void *ud); 206*c99fb5f9SBaptiste Daroussin /** Append a string of a specified length */ 207*c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_len) (unsigned const char *str, size_t len, void *ud); 208*c99fb5f9SBaptiste Daroussin /** Append a 64 bit integer */ 209*c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_int) (int64_t elt, void *ud); 210*c99fb5f9SBaptiste Daroussin /** Append floating point element */ 211*c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_double) (double elt, void *ud); 212*c99fb5f9SBaptiste Daroussin /** Opaque userdata pointer */ 213*c99fb5f9SBaptiste Daroussin void *ud; 214*c99fb5f9SBaptiste Daroussin}; 215*c99fb5f9SBaptiste Daroussin~~~ 216*c99fb5f9SBaptiste Daroussin 217*c99fb5f9SBaptiste DaroussinThis structure defines the following callbacks: 218*c99fb5f9SBaptiste Daroussin 219*c99fb5f9SBaptiste Daroussin- `ucl_emitter_append_character` - a function that is called to append `nchars` characters equal to `c` 220*c99fb5f9SBaptiste Daroussin- `ucl_emitter_append_len` - used to append a string of length `len` starting from pointer `str` 221*c99fb5f9SBaptiste Daroussin- `ucl_emitter_append_int` - this function applies to integer numbers 222*c99fb5f9SBaptiste Daroussin- `ucl_emitter_append_double` - this function is intended to output floating point variable 223*c99fb5f9SBaptiste Daroussin 224*c99fb5f9SBaptiste DaroussinThe set of these functions could be used to output text formats of `UCL` objects to different structures or streams. 225*c99fb5f9SBaptiste Daroussin 226*c99fb5f9SBaptiste DaroussinLibucl provides the following functions for emitting UCL objects: 227*c99fb5f9SBaptiste Daroussin 228*c99fb5f9SBaptiste Daroussin### ucl_object_emit 229*c99fb5f9SBaptiste Daroussin 230*c99fb5f9SBaptiste Daroussin~~~C 231*c99fb5f9SBaptiste Daroussinunsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); 232*c99fb5f9SBaptiste Daroussin~~~ 233*c99fb5f9SBaptiste Daroussin 234*c99fb5f9SBaptiste DaroussinAllocate a string that is suitable to fit the underlying UCL object `obj` and fill it with the textual representation of the object `obj` according to style `emit_type`. The caller should free the returned string after using. 235*c99fb5f9SBaptiste Daroussin 236*c99fb5f9SBaptiste Daroussin### ucl_object_emit_full 237*c99fb5f9SBaptiste Daroussin 238*c99fb5f9SBaptiste Daroussin~~~C 239*c99fb5f9SBaptiste Daroussinbool ucl_object_emit_full (ucl_object_t *obj, enum ucl_emitter emit_type, 240*c99fb5f9SBaptiste Daroussin struct ucl_emitter_functions *emitter); 241*c99fb5f9SBaptiste Daroussin~~~ 242*c99fb5f9SBaptiste Daroussin 243*c99fb5f9SBaptiste DaroussinThis function is similar to the previous with the exception that it accepts the additional argument `emitter` that defines the concrete set of output functions. This emit function could be useful for custom structures or streams emitters (including C++ ones, for example). 244*c99fb5f9SBaptiste Daroussin 245*c99fb5f9SBaptiste Daroussin# Conversion functions 246*c99fb5f9SBaptiste Daroussin 247*c99fb5f9SBaptiste DaroussinConversion functions are used to convert UCL objects to primitive types, such as strings, numbers or boolean values. There are two types of conversion functions: 248*c99fb5f9SBaptiste Daroussin 249*c99fb5f9SBaptiste Daroussin- safe: try to convert an ucl object to a primitive type and fail if such a conversion is not possible 250*c99fb5f9SBaptiste Daroussin- unsafe: return primitive type without additional checks, if the object cannot be converted then some reasonable default is returned (NULL for strings and 0 for numbers) 251*c99fb5f9SBaptiste Daroussin 252*c99fb5f9SBaptiste DaroussinAlso there is a single `ucl_object_tostring_forced` function that converts any UCL object (including compound types - arrays and objects) to a string representation. For compound and numeric types this function performs emitting to a compact json format actually. 253*c99fb5f9SBaptiste Daroussin 254*c99fb5f9SBaptiste DaroussinHere is a list of all conversion functions: 255*c99fb5f9SBaptiste Daroussin 256*c99fb5f9SBaptiste Daroussin- `ucl_object_toint` - returns `int64_t` of UCL object 257*c99fb5f9SBaptiste Daroussin- `ucl_object_todouble` - returns `double` of UCL object 258*c99fb5f9SBaptiste Daroussin- `ucl_object_toboolean` - returns `bool` of UCL object 259*c99fb5f9SBaptiste Daroussin- `ucl_object_tostring` - returns `const char *` of UCL object (this string is NULL terminated) 260*c99fb5f9SBaptiste Daroussin- `ucl_object_tolstring` - returns `const char *` and `size_t` len of UCL object (string can be not NULL terminated) 261*c99fb5f9SBaptiste Daroussin- `ucl_object_tostring_forced` - returns string representation of any UCL object 262*c99fb5f9SBaptiste Daroussin 263*c99fb5f9SBaptiste DaroussinStrings returned by these pointers are associated with the UCL object and exist over its lifetime. A caller should not free this memory.