xref: /freebsd/contrib/libucl/doc/api.md (revision a0409676)
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