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