197bd480fSBaptiste Daroussin# API documentation 297bd480fSBaptiste Daroussin 397bd480fSBaptiste Daroussin**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* 497bd480fSBaptiste Daroussin 597bd480fSBaptiste Daroussin- [Synopsis](#synopsis) 697bd480fSBaptiste Daroussin- [Description](#description) 797bd480fSBaptiste Daroussin - [Parser functions](#parser-functions) 897bd480fSBaptiste Daroussin - [Emitting functions](#emitting-functions) 997bd480fSBaptiste Daroussin - [Conversion functions](#conversion-functions) 1097bd480fSBaptiste Daroussin - [Generation functions](#generation-functions) 1197bd480fSBaptiste Daroussin - [Iteration functions](#iteration-functions) 1297bd480fSBaptiste Daroussin - [Validation functions](#validation-functions) 1397bd480fSBaptiste Daroussin - [Utility functions](#utility-functions) 1497bd480fSBaptiste Daroussin- [Parser functions](#parser-functions-1) 1597bd480fSBaptiste Daroussin - [ucl_parser_new](#ucl_parser_new) 1697bd480fSBaptiste Daroussin - [ucl_parser_register_macro](#ucl_parser_register_macro) 1797bd480fSBaptiste Daroussin - [ucl_parser_register_variable](#ucl_parser_register_variable) 1897bd480fSBaptiste Daroussin - [ucl_parser_add_chunk](#ucl_parser_add_chunk) 1997bd480fSBaptiste Daroussin - [ucl_parser_add_string](#ucl_parser_add_string) 2097bd480fSBaptiste Daroussin - [ucl_parser_add_file](#ucl_parser_add_file) 2197bd480fSBaptiste Daroussin - [ucl_parser_get_object](#ucl_parser_get_object) 2297bd480fSBaptiste Daroussin - [ucl_parser_get_error](#ucl_parser_get_error) 2397bd480fSBaptiste Daroussin - [ucl_parser_free](#ucl_parser_free) 2497bd480fSBaptiste Daroussin - [ucl_pubkey_add](#ucl_pubkey_add) 2597bd480fSBaptiste Daroussin - [ucl_parser_set_filevars](#ucl_parser_set_filevars) 2697bd480fSBaptiste Daroussin - [Parser usage example](#parser-usage-example) 2797bd480fSBaptiste Daroussin- [Emitting functions](#emitting-functions-1) 2897bd480fSBaptiste Daroussin - [ucl_object_emit](#ucl_object_emit) 2997bd480fSBaptiste Daroussin - [ucl_object_emit_full](#ucl_object_emit_full) 3097bd480fSBaptiste Daroussin- [Conversion functions](#conversion-functions-1) 3197bd480fSBaptiste Daroussin- [Generation functions](#generation-functions-1) 3297bd480fSBaptiste Daroussin - [ucl_object_new](#ucl_object_new) 3397bd480fSBaptiste Daroussin - [ucl_object_typed_new](#ucl_object_typed_new) 3497bd480fSBaptiste Daroussin - [Primitive objects generation](#primitive-objects-generation) 3597bd480fSBaptiste Daroussin - [ucl_object_fromstring_common](#ucl_object_fromstring_common) 3697bd480fSBaptiste Daroussin- [Iteration functions](#iteration-functions-1) 3797bd480fSBaptiste Daroussin - [ucl_iterate_object](#ucl_iterate_object) 3897bd480fSBaptiste Daroussin- [Validation functions](#validation-functions-1) 3997bd480fSBaptiste Daroussin - [ucl_object_validate](#ucl_object_validate) 4097bd480fSBaptiste Daroussin 4197bd480fSBaptiste Daroussin# Synopsis 42c99fb5f9SBaptiste Daroussin 43c99fb5f9SBaptiste Daroussin`#include <ucl.h>` 44c99fb5f9SBaptiste Daroussin 4597bd480fSBaptiste Daroussin# Description 46c99fb5f9SBaptiste Daroussin 47c99fb5f9SBaptiste DaroussinLibucl is a parser and `C` API to parse and generate `ucl` objects. Libucl consist of several groups of functions: 48c99fb5f9SBaptiste Daroussin 49c99fb5f9SBaptiste Daroussin### Parser functions 5097bd480fSBaptiste DaroussinUsed to parse `ucl` files and provide interface to extract `ucl` object. Currently, `libucl` can parse only full `ucl` documents, for instance, it is impossible to parse a part of document and therefore it is impossible to use `libucl` as a streaming parser. In future, this limitation can be removed. 51c99fb5f9SBaptiste Daroussin 52c99fb5f9SBaptiste Daroussin### Emitting functions 5397bd480fSBaptiste DaroussinConvert `ucl` objects to some textual or binary representation. Currently, libucl supports the following exports: 5497bd480fSBaptiste Daroussin 553dcf5eb7SBaptiste Daroussin- `JSON` - valid json format (can possibly lose some original data, such as implicit arrays) 563dcf5eb7SBaptiste Daroussin- `Config` - human-readable configuration format (lossless) 5797bd480fSBaptiste Daroussin- `YAML` - embedded yaml format (has the same limitations as `json` output) 58c99fb5f9SBaptiste Daroussin 59c99fb5f9SBaptiste Daroussin### Conversion functions 6097bd480fSBaptiste DaroussinHelp to convert `ucl` objects to C types. These functions are used to convert `ucl_object_t` to C primitive types, such as numbers, strings or boolean values. 61c99fb5f9SBaptiste Daroussin 62c99fb5f9SBaptiste Daroussin### Generation functions 633dcf5eb7SBaptiste DaroussinAllow creation of `ucl` objects from C types and creating of complex `ucl` objects, such as hashes or arrays from primitive `ucl` objects, such as numbers or strings. 64c99fb5f9SBaptiste Daroussin 65c99fb5f9SBaptiste Daroussin### Iteration functions 6697bd480fSBaptiste DaroussinIterate over `ucl` complex objects or over a chain of values, for example when a key in an object has multiple values (that can be treated as implicit array or implicit consolidation). 6797bd480fSBaptiste Daroussin 6897bd480fSBaptiste Daroussin### Validation functions 6997bd480fSBaptiste DaroussinValidation functions are used to validate some object `obj` using json-schema compatible object `schema`. Both input and schema must be UCL objects to perform validation. 70c99fb5f9SBaptiste Daroussin 71c99fb5f9SBaptiste Daroussin### Utility functions 7297bd480fSBaptiste DaroussinProvide basic utilities to manage `ucl` objects: creating, removing, retaining and releasing reference count and so on. 73c99fb5f9SBaptiste Daroussin 74c99fb5f9SBaptiste Daroussin# Parser functions 75c99fb5f9SBaptiste Daroussin 76c99fb5f9SBaptiste DaroussinParser functions operates with `struct ucl_parser`. 77c99fb5f9SBaptiste Daroussin 78c99fb5f9SBaptiste Daroussin### ucl_parser_new 79c99fb5f9SBaptiste Daroussin 80c99fb5f9SBaptiste Daroussin~~~C 81c99fb5f9SBaptiste Daroussinstruct ucl_parser* ucl_parser_new (int flags); 82c99fb5f9SBaptiste Daroussin~~~ 83c99fb5f9SBaptiste Daroussin 84c99fb5f9SBaptiste DaroussinCreates new parser with the specified flags: 85c99fb5f9SBaptiste Daroussin 86c99fb5f9SBaptiste Daroussin- `UCL_PARSER_KEY_LOWERCASE` - lowercase keys parsed 87c99fb5f9SBaptiste 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) 8897bd480fSBaptiste Daroussin- `UCL_PARSER_NO_TIME` - treat time values as strings without parsing them as floats 89c99fb5f9SBaptiste Daroussin 90c99fb5f9SBaptiste Daroussin### ucl_parser_register_macro 91c99fb5f9SBaptiste Daroussin 92c99fb5f9SBaptiste Daroussin~~~C 93c99fb5f9SBaptiste Daroussinvoid ucl_parser_register_macro (struct ucl_parser *parser, 94c99fb5f9SBaptiste Daroussin const char *macro, ucl_macro_handler handler, void* ud); 95c99fb5f9SBaptiste Daroussin~~~ 96c99fb5f9SBaptiste Daroussin 97c99fb5f9SBaptiste DaroussinRegister new macro with name .`macro` parsed by handler `handler` that accepts opaque data pointer `ud`. Macro handler should be of the following type: 98c99fb5f9SBaptiste Daroussin 99c99fb5f9SBaptiste Daroussin~~~C 100c99fb5f9SBaptiste Daroussinbool (*ucl_macro_handler) (const unsigned char *data, 101c99fb5f9SBaptiste Daroussin size_t len, void* ud);` 102c99fb5f9SBaptiste Daroussin~~~ 103c99fb5f9SBaptiste Daroussin 104c99fb5f9SBaptiste 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. 105c99fb5f9SBaptiste Daroussin 106c99fb5f9SBaptiste Daroussin### ucl_parser_register_variable 107c99fb5f9SBaptiste Daroussin 108c99fb5f9SBaptiste Daroussin~~~C 109c99fb5f9SBaptiste Daroussinvoid ucl_parser_register_variable (struct ucl_parser *parser, 110c99fb5f9SBaptiste Daroussin const char *var, const char *value); 111c99fb5f9SBaptiste Daroussin~~~ 112c99fb5f9SBaptiste Daroussin 113c99fb5f9SBaptiste DaroussinRegister new variable $`var` that should be replaced by the parser to the `value` string. 114c99fb5f9SBaptiste Daroussin 115c99fb5f9SBaptiste Daroussin### ucl_parser_add_chunk 116c99fb5f9SBaptiste Daroussin 117c99fb5f9SBaptiste Daroussin~~~C 118c99fb5f9SBaptiste Daroussinbool ucl_parser_add_chunk (struct ucl_parser *parser, 119c99fb5f9SBaptiste Daroussin const unsigned char *data, size_t len); 120c99fb5f9SBaptiste Daroussin~~~ 121c99fb5f9SBaptiste Daroussin 122c99fb5f9SBaptiste 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: 123c99fb5f9SBaptiste Daroussin 124c99fb5f9SBaptiste Daroussin~~~json 125c99fb5f9SBaptiste Daroussin{ "var": "value" } 126c99fb5f9SBaptiste Daroussin~~~ 127c99fb5f9SBaptiste Daroussin 128c99fb5f9SBaptiste Daroussinwhile this one won't be parsed correctly: 129c99fb5f9SBaptiste Daroussin 130c99fb5f9SBaptiste Daroussin~~~json 131c99fb5f9SBaptiste Daroussin{ "var": 132c99fb5f9SBaptiste Daroussin~~~ 133c99fb5f9SBaptiste Daroussin 134c99fb5f9SBaptiste DaroussinThis limitation may possible be removed in future. 135c99fb5f9SBaptiste Daroussin 13697bd480fSBaptiste Daroussin### ucl_parser_add_string 13797bd480fSBaptiste Daroussin~~~C 13897bd480fSBaptiste Daroussinbool ucl_parser_add_string (struct ucl_parser *parser, 13997bd480fSBaptiste Daroussin const char *data, size_t len); 14097bd480fSBaptiste Daroussin~~~ 14197bd480fSBaptiste Daroussin 14297bd480fSBaptiste DaroussinThis function acts exactly like `ucl_parser_add_chunk` does but if `len` argument is zero, then the string `data` must be zero-terminated and the actual length is calculated up to `\0` character. 14397bd480fSBaptiste Daroussin 144c99fb5f9SBaptiste Daroussin### ucl_parser_add_file 145c99fb5f9SBaptiste Daroussin 146c99fb5f9SBaptiste Daroussin~~~C 147c99fb5f9SBaptiste Daroussinbool ucl_parser_add_file (struct ucl_parser *parser, 148c99fb5f9SBaptiste Daroussin const char *filename); 149c99fb5f9SBaptiste Daroussin~~~ 150c99fb5f9SBaptiste Daroussin 1513dcf5eb7SBaptiste DaroussinLoad file `filename` and parse it with the specified `parser`. This function uses `mmap` call to load file, therefore, it should not be `shrunk` 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. 152c99fb5f9SBaptiste Daroussin 153c99fb5f9SBaptiste Daroussin### ucl_parser_get_object 154c99fb5f9SBaptiste Daroussin 155c99fb5f9SBaptiste Daroussin~~~C 156c99fb5f9SBaptiste Daroussinucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); 157c99fb5f9SBaptiste Daroussin~~~ 158c99fb5f9SBaptiste Daroussin 159c99fb5f9SBaptiste 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. 160c99fb5f9SBaptiste Daroussin 161c99fb5f9SBaptiste Daroussin### ucl_parser_get_error 162c99fb5f9SBaptiste Daroussin 163c99fb5f9SBaptiste Daroussin~~~C 164c99fb5f9SBaptiste Daroussinconst char *ucl_parser_get_error(struct ucl_parser *parser); 165c99fb5f9SBaptiste Daroussin~~~ 166c99fb5f9SBaptiste Daroussin 167c99fb5f9SBaptiste 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. 168c99fb5f9SBaptiste Daroussin 169c99fb5f9SBaptiste Daroussin### ucl_parser_free 170c99fb5f9SBaptiste Daroussin 171c99fb5f9SBaptiste Daroussin~~~C 172c99fb5f9SBaptiste Daroussinvoid ucl_parser_free (struct ucl_parser *parser); 173c99fb5f9SBaptiste Daroussin~~~ 174c99fb5f9SBaptiste Daroussin 175c99fb5f9SBaptiste 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. 176c99fb5f9SBaptiste Daroussin 177c99fb5f9SBaptiste Daroussin### ucl_pubkey_add 178c99fb5f9SBaptiste Daroussin 179c99fb5f9SBaptiste Daroussin~~~C 180c99fb5f9SBaptiste Daroussinbool ucl_pubkey_add (struct ucl_parser *parser, 181c99fb5f9SBaptiste Daroussin const unsigned char *key, size_t len); 182c99fb5f9SBaptiste Daroussin~~~ 183c99fb5f9SBaptiste Daroussin 184c99fb5f9SBaptiste 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`. 185c99fb5f9SBaptiste Daroussin 186c99fb5f9SBaptiste Daroussin### ucl_parser_set_filevars 187c99fb5f9SBaptiste Daroussin 188c99fb5f9SBaptiste Daroussin~~~C 189c99fb5f9SBaptiste Daroussinbool ucl_parser_set_filevars (struct ucl_parser *parser, 190c99fb5f9SBaptiste Daroussin const char *filename, bool need_expand); 191c99fb5f9SBaptiste Daroussin~~~ 192c99fb5f9SBaptiste Daroussin 193c99fb5f9SBaptiste DaroussinAdd the standard file variables to the `parser` based on the `filename` specified: 194c99fb5f9SBaptiste Daroussin 195c99fb5f9SBaptiste Daroussin- `$FILENAME` - a filename of `ucl` input 196c99fb5f9SBaptiste Daroussin- `$CURDIR` - a current directory of the input 197c99fb5f9SBaptiste Daroussin 198c99fb5f9SBaptiste DaroussinFor example, if a `filename` param is `../something.conf` then the variables will have the following values: 199c99fb5f9SBaptiste Daroussin 200c99fb5f9SBaptiste Daroussin- `$FILENAME` - "../something.conf" 201c99fb5f9SBaptiste Daroussin- `$CURDIR` - ".." 202c99fb5f9SBaptiste Daroussin 203c99fb5f9SBaptiste 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: 204c99fb5f9SBaptiste Daroussin 205c99fb5f9SBaptiste Daroussin- `$FILENAME` - "/etc/something.conf" 206c99fb5f9SBaptiste Daroussin- `$CURDIR` - "/etc" 207c99fb5f9SBaptiste Daroussin 208c99fb5f9SBaptiste Daroussin## Parser usage example 209c99fb5f9SBaptiste Daroussin 210c99fb5f9SBaptiste DaroussinThe following example loads, parses and extracts `ucl` object from stdin using `libucl` parser functions (the length of input is limited to 8K): 211c99fb5f9SBaptiste Daroussin 212c99fb5f9SBaptiste Daroussin~~~C 213c99fb5f9SBaptiste Daroussinchar inbuf[8192]; 214c99fb5f9SBaptiste Daroussinstruct ucl_parser *parser = NULL; 215c99fb5f9SBaptiste Daroussinint ret = 0, r = 0; 216c99fb5f9SBaptiste Daroussinucl_object_t *obj = NULL; 217c99fb5f9SBaptiste DaroussinFILE *in; 218c99fb5f9SBaptiste Daroussin 219c99fb5f9SBaptiste Daroussinin = stdin; 220c99fb5f9SBaptiste Daroussinparser = ucl_parser_new (0); 221c99fb5f9SBaptiste Daroussinwhile (!feof (in) && r < (int)sizeof (inbuf)) { 222c99fb5f9SBaptiste Daroussin r += fread (inbuf + r, 1, sizeof (inbuf) - r, in); 223c99fb5f9SBaptiste Daroussin} 224c99fb5f9SBaptiste Daroussinucl_parser_add_chunk (parser, inbuf, r); 225c99fb5f9SBaptiste Daroussinfclose (in); 226c99fb5f9SBaptiste Daroussin 227c99fb5f9SBaptiste Daroussinif (ucl_parser_get_error (parser)) { 2283dcf5eb7SBaptiste Daroussin printf ("Error occurred: %s\n", ucl_parser_get_error (parser)); 229c99fb5f9SBaptiste Daroussin ret = 1; 230c99fb5f9SBaptiste Daroussin} 231c99fb5f9SBaptiste Daroussinelse { 232c99fb5f9SBaptiste Daroussin obj = ucl_parser_get_object (parser); 233c99fb5f9SBaptiste Daroussin} 234c99fb5f9SBaptiste Daroussin 235c99fb5f9SBaptiste Daroussinif (parser != NULL) { 236c99fb5f9SBaptiste Daroussin ucl_parser_free (parser); 237c99fb5f9SBaptiste Daroussin} 238c99fb5f9SBaptiste Daroussinif (obj != NULL) { 239c99fb5f9SBaptiste Daroussin ucl_object_unref (obj); 240c99fb5f9SBaptiste Daroussin} 241c99fb5f9SBaptiste Daroussinreturn ret; 242c99fb5f9SBaptiste Daroussin~~~ 243c99fb5f9SBaptiste Daroussin 244c99fb5f9SBaptiste Daroussin# Emitting functions 245c99fb5f9SBaptiste Daroussin 246*a0409676SBaptiste DaroussinLibucl can transform UCL objects to a number of textual formats: 247c99fb5f9SBaptiste Daroussin 248c99fb5f9SBaptiste Daroussin- configuration (`UCL_EMIT_CONFIG`) - nginx like human readable configuration file where implicit arrays are transformed to the duplicate keys 249c99fb5f9SBaptiste Daroussin- compact json: `UCL_EMIT_JSON_COMPACT` - single line valid json without spaces 250c99fb5f9SBaptiste Daroussin- formatted json: `UCL_EMIT_JSON` - pretty formatted JSON with newlines and spaces 251c99fb5f9SBaptiste Daroussin- compact yaml: `UCL_EMIT_YAML` - compact YAML output 252c99fb5f9SBaptiste Daroussin 253c99fb5f9SBaptiste DaroussinMoreover, libucl API allows to select a custom set of emitting functions allowing 2543dcf5eb7SBaptiste Daroussinefficient and zero-copy output of libucl objects. Libucl uses the following structure to support this feature: 255c99fb5f9SBaptiste Daroussin 256c99fb5f9SBaptiste Daroussin~~~C 257c99fb5f9SBaptiste Daroussinstruct ucl_emitter_functions { 258c99fb5f9SBaptiste Daroussin /** Append a single character */ 259c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_character) (unsigned char c, size_t nchars, void *ud); 260c99fb5f9SBaptiste Daroussin /** Append a string of a specified length */ 261c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_len) (unsigned const char *str, size_t len, void *ud); 262c99fb5f9SBaptiste Daroussin /** Append a 64 bit integer */ 263c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_int) (int64_t elt, void *ud); 264c99fb5f9SBaptiste Daroussin /** Append floating point element */ 265c99fb5f9SBaptiste Daroussin int (*ucl_emitter_append_double) (double elt, void *ud); 266c99fb5f9SBaptiste Daroussin /** Opaque userdata pointer */ 267c99fb5f9SBaptiste Daroussin void *ud; 268c99fb5f9SBaptiste Daroussin}; 269c99fb5f9SBaptiste Daroussin~~~ 270c99fb5f9SBaptiste Daroussin 271c99fb5f9SBaptiste DaroussinThis structure defines the following callbacks: 272c99fb5f9SBaptiste Daroussin 273c99fb5f9SBaptiste Daroussin- `ucl_emitter_append_character` - a function that is called to append `nchars` characters equal to `c` 274c99fb5f9SBaptiste Daroussin- `ucl_emitter_append_len` - used to append a string of length `len` starting from pointer `str` 275c99fb5f9SBaptiste Daroussin- `ucl_emitter_append_int` - this function applies to integer numbers 276c99fb5f9SBaptiste Daroussin- `ucl_emitter_append_double` - this function is intended to output floating point variable 277c99fb5f9SBaptiste Daroussin 278c99fb5f9SBaptiste DaroussinThe set of these functions could be used to output text formats of `UCL` objects to different structures or streams. 279c99fb5f9SBaptiste Daroussin 280c99fb5f9SBaptiste DaroussinLibucl provides the following functions for emitting UCL objects: 281c99fb5f9SBaptiste Daroussin 282c99fb5f9SBaptiste Daroussin### ucl_object_emit 283c99fb5f9SBaptiste Daroussin 284c99fb5f9SBaptiste Daroussin~~~C 285b04a7a0bSBaptiste Daroussinunsigned char *ucl_object_emit (const ucl_object_t *obj, enum ucl_emitter emit_type); 286c99fb5f9SBaptiste Daroussin~~~ 287c99fb5f9SBaptiste Daroussin 288c99fb5f9SBaptiste 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. 289c99fb5f9SBaptiste Daroussin 290c99fb5f9SBaptiste Daroussin### ucl_object_emit_full 291c99fb5f9SBaptiste Daroussin 292c99fb5f9SBaptiste Daroussin~~~C 293b04a7a0bSBaptiste Daroussinbool ucl_object_emit_full (const ucl_object_t *obj, enum ucl_emitter emit_type, 294c99fb5f9SBaptiste Daroussin struct ucl_emitter_functions *emitter); 295c99fb5f9SBaptiste Daroussin~~~ 296c99fb5f9SBaptiste Daroussin 297c99fb5f9SBaptiste 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). 298c99fb5f9SBaptiste Daroussin 299c99fb5f9SBaptiste Daroussin# Conversion functions 300c99fb5f9SBaptiste Daroussin 3013dcf5eb7SBaptiste 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: 302c99fb5f9SBaptiste Daroussin 303c99fb5f9SBaptiste Daroussin- safe: try to convert an ucl object to a primitive type and fail if such a conversion is not possible 304c99fb5f9SBaptiste 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) 305c99fb5f9SBaptiste Daroussin 3063dcf5eb7SBaptiste 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 objects, arrays, booleans and numeric types this function performs emitting to a compact json format actually. 307c99fb5f9SBaptiste Daroussin 308c99fb5f9SBaptiste DaroussinHere is a list of all conversion functions: 309c99fb5f9SBaptiste Daroussin 310c99fb5f9SBaptiste Daroussin- `ucl_object_toint` - returns `int64_t` of UCL object 311c99fb5f9SBaptiste Daroussin- `ucl_object_todouble` - returns `double` of UCL object 312c99fb5f9SBaptiste Daroussin- `ucl_object_toboolean` - returns `bool` of UCL object 313c99fb5f9SBaptiste Daroussin- `ucl_object_tostring` - returns `const char *` of UCL object (this string is NULL terminated) 3143dcf5eb7SBaptiste Daroussin- `ucl_object_tolstring` - returns `const char *` and `size_t` len of UCL object (string does not need to be NULL terminated) 315c99fb5f9SBaptiste Daroussin- `ucl_object_tostring_forced` - returns string representation of any UCL object 316c99fb5f9SBaptiste Daroussin 317c99fb5f9SBaptiste DaroussinStrings returned by these pointers are associated with the UCL object and exist over its lifetime. A caller should not free this memory. 31836c53d67SBaptiste Daroussin 31936c53d67SBaptiste Daroussin# Generation functions 32036c53d67SBaptiste Daroussin 3213dcf5eb7SBaptiste DaroussinIt is possible to generate UCL objects from C primitive types. Moreover, libucl allows creation and modifying complex UCL objects, such as arrays or associative objects. 32236c53d67SBaptiste Daroussin 32336c53d67SBaptiste Daroussin## ucl_object_new 32436c53d67SBaptiste Daroussin~~~C 32536c53d67SBaptiste Daroussinucl_object_t * ucl_object_new (void) 32636c53d67SBaptiste Daroussin~~~ 32736c53d67SBaptiste Daroussin 32836c53d67SBaptiste DaroussinCreates new object of type `UCL_NULL`. This object should be released by caller. 32936c53d67SBaptiste Daroussin 33036c53d67SBaptiste Daroussin## ucl_object_typed_new 33136c53d67SBaptiste Daroussin~~~C 33236c53d67SBaptiste Daroussinucl_object_t * ucl_object_typed_new (unsigned int type) 33336c53d67SBaptiste Daroussin~~~ 33436c53d67SBaptiste Daroussin 33536c53d67SBaptiste DaroussinCreate an object of a specified type: 33636c53d67SBaptiste Daroussin- `UCL_OBJECT` - UCL object - key/value pairs 33736c53d67SBaptiste Daroussin- `UCL_ARRAY` - UCL array 33836c53d67SBaptiste Daroussin- `UCL_INT` - integer number 33936c53d67SBaptiste Daroussin- `UCL_FLOAT` - floating point number 34036c53d67SBaptiste Daroussin- `UCL_STRING` - NULL terminated string 34136c53d67SBaptiste Daroussin- `UCL_BOOLEAN` - boolean value 34236c53d67SBaptiste Daroussin- `UCL_TIME` - time value (floating point number of seconds) 34336c53d67SBaptiste Daroussin- `UCL_USERDATA` - opaque userdata pointer (may be used in macros) 34436c53d67SBaptiste Daroussin- `UCL_NULL` - null value 34536c53d67SBaptiste Daroussin 34636c53d67SBaptiste DaroussinThis object should be released by caller. 34736c53d67SBaptiste Daroussin 34836c53d67SBaptiste Daroussin## Primitive objects generation 34936c53d67SBaptiste DaroussinLibucl provides the functions similar to inverse conversion functions called with the specific C type: 35036c53d67SBaptiste Daroussin- `ucl_object_fromint` - converts `int64_t` to UCL object 35136c53d67SBaptiste Daroussin- `ucl_object_fromdouble` - converts `double` to UCL object 352*a0409676SBaptiste Daroussin- `ucl_object_frombool` - converts `bool` to UCL object 3533dcf5eb7SBaptiste Daroussin- `ucl_object_fromstring` - converts `const char *` to UCL object (this string should be NULL terminated) 3543dcf5eb7SBaptiste Daroussin- `ucl_object_fromlstring` - converts `const char *` and `size_t` len to UCL object (string does not need to be NULL terminated) 35536c53d67SBaptiste Daroussin 35636c53d67SBaptiste DaroussinAlso there is a function to generate UCL object from a string performing various parsing or conversion operations called `ucl_object_fromstring_common`. 35736c53d67SBaptiste Daroussin 35836c53d67SBaptiste Daroussin## ucl_object_fromstring_common 35936c53d67SBaptiste Daroussin~~~C 36036c53d67SBaptiste Daroussinucl_object_t * ucl_object_fromstring_common (const char *str, 36136c53d67SBaptiste Daroussin size_t len, enum ucl_string_flags flags) 36236c53d67SBaptiste Daroussin~~~ 36336c53d67SBaptiste Daroussin 3643dcf5eb7SBaptiste DaroussinThis function is used to convert a string `str` of size `len` to a UCL object applying `flags` conversions. If `len` is equal to zero then a `str` is assumed as NULL-terminated. This function supports the following flags (a set of flags can be specified using logical `OR` operation): 36536c53d67SBaptiste Daroussin 36636c53d67SBaptiste Daroussin- `UCL_STRING_ESCAPE` - perform JSON escape 36736c53d67SBaptiste Daroussin- `UCL_STRING_TRIM` - trim leading and trailing whitespaces 36836c53d67SBaptiste Daroussin- `UCL_STRING_PARSE_BOOLEAN` - parse passed string and detect boolean 36936c53d67SBaptiste Daroussin- `UCL_STRING_PARSE_INT` - parse passed string and detect integer number 37036c53d67SBaptiste Daroussin- `UCL_STRING_PARSE_DOUBLE` - parse passed string and detect integer or float number 37197bd480fSBaptiste Daroussin- `UCL_STRING_PARSE_TIME` - parse time values as floating point numbers 37297bd480fSBaptiste Daroussin- `UCL_STRING_PARSE_NUMBER` - parse passed string and detect number (both float, integer and time types) 37397bd480fSBaptiste Daroussin- `UCL_STRING_PARSE` - parse passed string (and detect booleans, numbers and time values) 37436c53d67SBaptiste Daroussin- `UCL_STRING_PARSE_BYTES` - assume that numeric multipliers are in bytes notation, for example `10k` means `10*1024` and not `10*1000` as assumed without this flag 37536c53d67SBaptiste Daroussin 37636c53d67SBaptiste DaroussinIf parsing operations fail then the resulting UCL object will be a `UCL_STRING`. A caller should always check the type of the returned object and release it after using. 37736c53d67SBaptiste Daroussin 37897bd480fSBaptiste Daroussin# Iteration functions 37936c53d67SBaptiste Daroussin 3808e3b1ab2SBaptiste DaroussinIteration are used to iterate over UCL compound types: arrays and objects. Moreover, iterations could be performed over the keys with multiple values (implicit arrays). 3818e3b1ab2SBaptiste DaroussinThere are two types of iterators API: old and unsafe one via `ucl_iterate_object` and the proposed interface of safe iterators. 3828e3b1ab2SBaptiste Daroussin 38336c53d67SBaptiste Daroussin 38436c53d67SBaptiste Daroussin## ucl_iterate_object 38536c53d67SBaptiste Daroussin~~~C 386b04a7a0bSBaptiste Daroussinconst ucl_object_t* ucl_iterate_object (const ucl_object_t *obj, 38736c53d67SBaptiste Daroussin ucl_object_iter_t *iter, bool expand_values); 38836c53d67SBaptiste Daroussin~~~ 38936c53d67SBaptiste Daroussin 3903dcf5eb7SBaptiste DaroussinThis function accepts opaque iterator pointer `iter`. In the first call this iterator *must* be initialized to `NULL`. Iterator is changed by this function call. `ucl_iterate_object` returns the next UCL object in the compound object `obj` or `NULL` if all objects have been iterated. The reference count of the object returned is not increased, so a caller should not unref the object or modify its content (e.g. by inserting to another compound object). The object `obj` should not be changed during the iteration process as well. `expand_values` flag speicifies whether `ucl_iterate_object` should expand keys with multiple values. The general rule is that if you need to iterate through the *object* or *explicit array*, then you always need to set this flag to `true`. However, if you get some key in the object and want to extract all its values then you should set `expand_values` to `false`. Mixing of iteration types is not permitted since the iterator is set according to the iteration type and cannot be reused. Here is an example of iteration over the objects using libucl API (assuming that `top` is `UCL_OBJECT` in this example): 39136c53d67SBaptiste Daroussin 39236c53d67SBaptiste Daroussin~~~C 39336c53d67SBaptiste Daroussinucl_object_iter_t it = NULL, it_obj = NULL; 394b04a7a0bSBaptiste Daroussinconst ucl_object_t *cur, *tmp; 39536c53d67SBaptiste Daroussin 39636c53d67SBaptiste Daroussin/* Iterate over the object */ 39736c53d67SBaptiste Daroussinwhile ((obj = ucl_iterate_object (top, &it, true))) { 39836c53d67SBaptiste Daroussin printf ("key: \"%s\"\n", ucl_object_key (obj)); 39936c53d67SBaptiste Daroussin /* Iterate over the values of a key */ 40036c53d67SBaptiste Daroussin while ((cur = ucl_iterate_object (obj, &it_obj, false))) { 40136c53d67SBaptiste Daroussin printf ("value: \"%s\"\n", 40236c53d67SBaptiste Daroussin ucl_object_tostring_forced (cur)); 40336c53d67SBaptiste Daroussin } 40436c53d67SBaptiste Daroussin} 40536c53d67SBaptiste Daroussin~~~ 40697bd480fSBaptiste Daroussin 4078e3b1ab2SBaptiste Daroussin## Safe iterators API 4088e3b1ab2SBaptiste Daroussin 4098e3b1ab2SBaptiste DaroussinSafe iterators are defined to clarify iterating over UCL objects and simplify flattening of UCL objects in non-trivial cases. 4108e3b1ab2SBaptiste DaroussinFor example, if there is an implicit array that contains another array and a boolean value it is extremely unclear how to iterate over 4118e3b1ab2SBaptiste Daroussinsuch an object. Safe iterators are desinged to define two sorts of iteration: 4128e3b1ab2SBaptiste Daroussin 4138e3b1ab2SBaptiste Daroussin1. Iteration over complex objects with expanding all values 4148e3b1ab2SBaptiste Daroussin2. Iteration over complex objects without expanding of values 4158e3b1ab2SBaptiste Daroussin 4168e3b1ab2SBaptiste DaroussinThe following example demonstrates the difference between these two types of iteration: 4178e3b1ab2SBaptiste Daroussin 4188e3b1ab2SBaptiste Daroussin~~~ 4198e3b1ab2SBaptiste Daroussinkey = 1; 4208e3b1ab2SBaptiste Daroussinkey = [2, 3, 4]; 4218e3b1ab2SBaptiste Daroussin 4228e3b1ab2SBaptiste DaroussinIteration with expansion: 4238e3b1ab2SBaptiste Daroussin 4248e3b1ab2SBaptiste Daroussin1, 2, 3, 4 4258e3b1ab2SBaptiste Daroussin 4268e3b1ab2SBaptiste DaroussinIteration without expansion: 4278e3b1ab2SBaptiste Daroussin 4288e3b1ab2SBaptiste Daroussin1, [2, 3, 4] 4298e3b1ab2SBaptiste Daroussin~~~ 4308e3b1ab2SBaptiste Daroussin 4318e3b1ab2SBaptiste DaroussinUCL defines the following functions to manage safe iterators: 4328e3b1ab2SBaptiste Daroussin 4338e3b1ab2SBaptiste Daroussin- `ucl_object_iterate_new` - creates new safe iterator 4348e3b1ab2SBaptiste Daroussin- `ucl_object_iterate_reset` - resets iterator to a new object 435*a0409676SBaptiste Daroussin- `ucl_object_iterate_safe` - safely iterate the object inside iterator. Note: function may allocate and free memory during its operation. Therefore it returns `NULL` either while trying to access item after the last one or when exception (such as memory allocation failure) happens. 436*a0409676SBaptiste Daroussin- `ucl_object_iter_chk_excpn` - check if the last call to `ucl_object_iterate_safe` ended up in unrecoverable exception (e.g. `ENOMEM`). 4378e3b1ab2SBaptiste Daroussin- `ucl_object_iterate_free` - free memory associated with the safe iterator 4388e3b1ab2SBaptiste Daroussin 4398e3b1ab2SBaptiste DaroussinPlease note that unlike unsafe iterators, safe iterators *must* be explicitly initialized and freed. 4408e3b1ab2SBaptiste DaroussinAn assert is likely generated if you use uninitialized or `NULL` iterator in all safe iterators functions. 4418e3b1ab2SBaptiste Daroussin 4428e3b1ab2SBaptiste Daroussin~~~C 4438e3b1ab2SBaptiste Daroussinucl_object_iter_t it; 4448e3b1ab2SBaptiste Daroussinconst ucl_object_t *cur; 4458e3b1ab2SBaptiste Daroussin 4468e3b1ab2SBaptiste Daroussinit = ucl_object_iterate_new (obj); 4478e3b1ab2SBaptiste Daroussin 4488e3b1ab2SBaptiste Daroussinwhile ((cur = ucl_object_iterate_safe (it, true)) != NULL) { 4498e3b1ab2SBaptiste Daroussin /* Do something */ 4508e3b1ab2SBaptiste Daroussin} 451*a0409676SBaptiste Daroussin/* Check error condition */ 452*a0409676SBaptiste Daroussinif (ucl_object_iter_chk_excpn (it)) { 453*a0409676SBaptiste Daroussin ucl_object_iterate_free (it); 454*a0409676SBaptiste Daroussin exit (1); 455*a0409676SBaptiste Daroussin} 4568e3b1ab2SBaptiste Daroussin 4578e3b1ab2SBaptiste Daroussin/* Switch to another object */ 4588e3b1ab2SBaptiste Daroussinit = ucl_object_iterate_reset (it, another_obj); 4598e3b1ab2SBaptiste Daroussin 4608e3b1ab2SBaptiste Daroussinwhile ((cur = ucl_object_iterate_safe (it, true)) != NULL) { 4618e3b1ab2SBaptiste Daroussin /* Do something else */ 4628e3b1ab2SBaptiste Daroussin} 463*a0409676SBaptiste Daroussin/* Check error condition */ 464*a0409676SBaptiste Daroussinif (ucl_object_iter_chk_excpn (it)) { 465*a0409676SBaptiste Daroussin ucl_object_iterate_free (it); 466*a0409676SBaptiste Daroussin exit (1); 467*a0409676SBaptiste Daroussin} 4688e3b1ab2SBaptiste Daroussin 4698e3b1ab2SBaptiste Daroussinucl_object_iterate_free (it); 4708e3b1ab2SBaptiste Daroussin~~~ 4718e3b1ab2SBaptiste Daroussin 47297bd480fSBaptiste Daroussin# Validation functions 47397bd480fSBaptiste Daroussin 47497bd480fSBaptiste DaroussinCurrently, there is only one validation function called `ucl_object_validate`. It performs validation of object using the specified schema. This function is defined as following: 47597bd480fSBaptiste Daroussin 47697bd480fSBaptiste Daroussin## ucl_object_validate 47797bd480fSBaptiste Daroussin~~~C 478b04a7a0bSBaptiste Daroussinbool ucl_object_validate (const ucl_object_t *schema, 479b04a7a0bSBaptiste Daroussin const ucl_object_t *obj, struct ucl_schema_error *err); 48097bd480fSBaptiste Daroussin~~~ 48197bd480fSBaptiste Daroussin 4823dcf5eb7SBaptiste DaroussinThis function uses ucl object `schema`, that must be valid in terms of `json-schema` draft v4, to validate input object `obj`. If this function returns `true` then validation procedure has been succeed. Otherwise, `false` is returned and `err` is set to a specific value. If a caller sets `err` to NULL then this function does not set any error just returning `false`. Error is the structure defined as following: 48397bd480fSBaptiste Daroussin 48497bd480fSBaptiste Daroussin~~~C 48597bd480fSBaptiste Daroussinstruct ucl_schema_error { 48697bd480fSBaptiste Daroussin enum ucl_schema_error_code code; /* error code */ 48797bd480fSBaptiste Daroussin char msg[128]; /* error message */ 4883dcf5eb7SBaptiste Daroussin ucl_object_t *obj; /* object where error occurred */ 48997bd480fSBaptiste Daroussin}; 49097bd480fSBaptiste Daroussin~~~ 49197bd480fSBaptiste Daroussin 49297bd480fSBaptiste DaroussinCaller may use `code` field to get a numeric error code: 49397bd480fSBaptiste Daroussin 49497bd480fSBaptiste Daroussin~~~C 49597bd480fSBaptiste Daroussinenum ucl_schema_error_code { 49697bd480fSBaptiste Daroussin UCL_SCHEMA_OK = 0, /* no error */ 49797bd480fSBaptiste Daroussin UCL_SCHEMA_TYPE_MISMATCH, /* type of object is incorrect */ 49897bd480fSBaptiste Daroussin UCL_SCHEMA_INVALID_SCHEMA, /* schema is invalid */ 49997bd480fSBaptiste Daroussin UCL_SCHEMA_MISSING_PROPERTY,/* missing properties */ 50097bd480fSBaptiste Daroussin UCL_SCHEMA_CONSTRAINT, /* constraint found */ 50197bd480fSBaptiste Daroussin UCL_SCHEMA_MISSING_DEPENDENCY, /* missing dependency */ 50297bd480fSBaptiste Daroussin UCL_SCHEMA_UNKNOWN /* generic error */ 50397bd480fSBaptiste Daroussin}; 50497bd480fSBaptiste Daroussin~~~ 50597bd480fSBaptiste Daroussin 5063dcf5eb7SBaptiste Daroussin`msg` is a string description of an error and `obj` is an object where error has occurred. Error object is not allocated by libucl, so there is no need to free it after validation (a static object should thus be used). 507