remove schema_len, use a sentinel
[protos/libecoli.git] / lib / ecoli_config.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2018, Olivier MATZ <zer0@droids-corp.org>
3  */
4
5 #ifndef ECOLI_CONFIG_
6 #define ECOLI_CONFIG_
7
8 #include <sys/queue.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12
13 #ifndef EC_COUNT_OF //XXX
14 #define EC_COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / \
15                 ((size_t)(!(sizeof(x) % sizeof(0[x])))))
16 #endif
17
18 struct ec_config;
19 struct ec_keyval;
20
21 /**
22  * The type identifier for a config value.
23  */
24 enum ec_config_type {
25         EC_CONFIG_TYPE_NONE = 0,
26         EC_CONFIG_TYPE_BOOL,
27         EC_CONFIG_TYPE_INT64,
28         EC_CONFIG_TYPE_UINT64,
29         EC_CONFIG_TYPE_STRING,
30         EC_CONFIG_TYPE_NODE,
31         EC_CONFIG_TYPE_LIST,
32         EC_CONFIG_TYPE_DICT,
33 };
34
35 /**
36  * Structure describing the format of a configuration value.
37  *
38  * This structure is used in a const array which is referenced by a
39  * struct ec_config. Each entry of the array represents a key/value
40  * storage of the configuration dictionary.
41  */
42 struct ec_config_schema {
43         const char *key;          /**< The key string (NULL for list elts). */
44         const char *desc;         /**< A description of the value. */
45         enum ec_config_type type; /**< Type of the value */
46
47         /** If type is dict or list, the schema of the dict or list
48          * elements. Else must be NULL. */
49         const struct ec_config_schema *subschema;
50 };
51
52 TAILQ_HEAD(ec_config_list, ec_config);
53
54 /**
55  * Structure storing the configuration data.
56  */
57 struct ec_config {
58         /** type of value stored in the union */
59         enum ec_config_type type;
60
61         union {
62                 bool boolean;   /** Boolean value */
63                 int64_t i64;    /** Signed integer value */
64                 uint64_t u64;   /** Unsigned integer value */
65                 char *string;   /** String value */
66                 struct ec_node *node;       /** Node value */
67                 struct ec_keyval *dict;     /** Hash table value */
68                 struct ec_config_list list; /** List value */
69         };
70
71         /**
72          * Next in list, only valid if type is list.
73          */
74         TAILQ_ENTRY(ec_config) next;
75 };
76
77 /* schema */
78
79 /**
80  * Validate a configuration schema array.
81  *
82  * @param schema
83  *   Pointer to the first element of the schema array. The array
84  *   must be terminated by a sentinel entry (type == EC_CONFIG_TYPE_NONE).
85  * @return
86  *   0 if the schema is valid, or -1 on error (errno is set).
87  */
88 int ec_config_schema_validate(const struct ec_config_schema *schema);
89
90 /**
91  * Dump a configuration schema array.
92  *
93  * @param out
94  *   Output stream on which the dump will be sent.
95  * @param schema
96  *   Pointer to the first element of the schema array. The array
97  *   must be terminated by a sentinel entry (type == EC_CONFIG_TYPE_NONE).
98  */
99 void ec_config_schema_dump(FILE *out, const struct ec_config_schema *schema);
100
101
102 /* config */
103
104 /**
105  * Get the type of the configuration.
106  *
107  * @param config
108  *   The configuration.
109  * @return
110  *   The configuration type.
111  */
112 enum ec_config_type ec_config_get_type(const struct ec_config *config);
113
114 /**
115  * Create a boolean configuration value.
116  *
117  * @param boolean
118  *   The boolean value to be set.
119  * @return
120  *   The configuration object, or NULL on error (errno is set).
121  */
122 struct ec_config *ec_config_bool(bool boolean);
123
124 /**
125  * Create a signed integer configuration value.
126  *
127  * @param i64
128  *   The signed integer value to be set.
129  * @return
130  *   The configuration object, or NULL on error (errno is set).
131  */
132 struct ec_config *ec_config_i64(int64_t i64);
133
134 /**
135  * Create an unsigned configuration value.
136  *
137  * @param u64
138  *   The unsigned integer value to be set.
139  * @return
140  *   The configuration object, or NULL on error (errno is set).
141  */
142 struct ec_config *ec_config_u64(uint64_t u64);
143
144 /**
145  * Create a string configuration value.
146  *
147  * @param string
148  *   The string value to be set. The string is copied into the
149  *   configuration object.
150  * @return
151  *   The configuration object, or NULL on error (errno is set).
152  */
153 struct ec_config *ec_config_string(const char *string);
154
155 /**
156  * Create a node configuration value.
157  *
158  * @param node
159  *   The node pointer to be set. The node is "consumed" by
160  *   the function and should not be used by the caller, even
161  *   on error. The caller can use ec_node_clone() to keep a
162  *   reference on the node.
163  * @return
164  *   The configuration object, or NULL on error (errno is set).
165  */
166 struct ec_config *ec_config_node(struct ec_node *node);
167
168 /**
169  * Create a hash table configuration value.
170  *
171  * @return
172  *   A configuration object containing an empty hash table, or NULL on
173  *   error (errno is set).
174  */
175 struct ec_config *ec_config_dict(void);
176
177 /**
178  * Create a list configuration value.
179  *
180  * @return
181  *   The configuration object containing an empty list, or NULL on
182  *   error (errno is set).
183  */
184 struct ec_config *ec_config_list(void);
185
186 /**
187  * Add a config object into a list.
188  *
189  * @param list
190  *   The list configuration in which the value will be added.
191  * @param value
192  *   The value configuration to add in the list. The value object
193  *   will be freed when freeing the list object. On error, the
194  *   value object is also freed.
195  * @return
196  *   0 on success, else -1 (errno is set).
197  */
198 int ec_config_list_add(struct ec_config *list, struct ec_config *value);
199
200 /**
201  * Remove an element from a list.
202  *
203  * The element is freed and should not be accessed.
204  *
205  * @param list
206  *   The list configuration.
207  * @param config
208  *   The element to remove from the list.
209  * @return
210  *   0 on success, -1 on error (errno is set).
211  */
212 int ec_config_list_del(struct ec_config *list, struct ec_config *config);
213
214 /**
215  * Validate a configuration.
216  *
217  * @param dict
218  *   A hash table configuration to validate.
219  * @param schema
220  *   Pointer to the first element of the schema array. The array
221  *   must be terminated by a sentinel entry (type == EC_CONFIG_TYPE_NONE).
222  * @return
223  *   0 on success, -1 on error (errno is set).
224  */
225 int ec_config_validate(const struct ec_config *dict,
226                 const struct ec_config_schema *schema);
227
228 /**
229  * Set a value in a hash table configuration
230  *
231  * @param dict
232  *   A hash table configuration to validate.
233  * @param key
234  *   The key to update.
235  * @param value
236  *   The value to set. The value object will be freed when freeing the
237  *   dict object. On error, the value object is also freed.
238  * @return
239  *   0 on success, -1 on error (errno is set).
240  */
241 int ec_config_dict_set(struct ec_config *dict, const char *key,
242                 struct ec_config *value);
243
244 /**
245  * Remove an element from a hash table configuration.
246  *
247  * The element is freed and should not be accessed.
248  *
249  * @param dict
250  *   A hash table configuration to validate.
251  * @param key
252  *   The key of the configuration to delete.
253  * @return
254  *   0 on success, -1 on error (errno is set).
255  */
256 int ec_config_dict_del(struct ec_config *config, const char *key);
257
258 /**
259  * Compare two configurations.
260  */
261 int ec_config_cmp(const struct ec_config *config1,
262                 const struct ec_config *config2);
263
264 /**
265  * Get configuration value.
266  */
267 struct ec_config *ec_config_dict_get(const struct ec_config *config,
268                                 const char *key);
269
270 /**
271  * Get the first element of a list.
272  *
273  * Example of use:
274  * for (config = ec_config_list_iter(list);
275  *      config != NULL;
276  *      config = ec_config_list_next(list, config)) {
277  *              ...
278  * }
279  *
280  * @param list
281  *   The list configuration to iterate.
282  * @return
283  *   The first configuration element, or NULL on error (errno is set).
284  */
285 struct ec_config *ec_config_list_first(struct ec_config *list);
286
287 /**
288  * Get next element in list.
289  *
290  * @param list
291  *   The list configuration beeing iterated.
292  * @param config
293  *   The current configuration element.
294  * @return
295  *   The next configuration element, or NULL if there is no more element.
296  */
297 struct ec_config *
298 ec_config_list_next(struct ec_config *list, struct ec_config *config);
299
300 /**
301  * Free a configuration.
302  *
303  * @param config
304  *   The element to free.
305  */
306 void ec_config_free(struct ec_config *config);
307
308 /**
309  * Compare two configurations.
310  *
311  * @return
312  *   0 if the configurations are equal, else -1.
313  */
314 int ec_config_cmp(const struct ec_config *value1,
315                 const struct ec_config *value2);
316
317 /**
318  * Duplicate a configuration.
319  *
320  * @param config
321  *   The configuration to duplicate.
322  * @return
323  *   The duplicated configuration, or NULL on error (errno is set).
324  */
325 struct ec_config *
326 ec_config_dup(const struct ec_config *config);
327
328 /**
329  * Dump a configuration.
330  *
331  * @param out
332  *   Output stream on which the dump will be sent.
333  * @param config
334  *   The configuration to dump.
335  */
336 void ec_config_dump(FILE *out, const struct ec_config *config);
337
338 #endif