24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
28 /** |
28 /** |
29 * \file properties.h |
29 * @file properties.h |
30 * \brief Interface for parsing data from properties files. |
30 * @brief Interface for parsing data from properties files. |
31 * \author Mike Becker |
31 * @author Mike Becker |
32 * \author Olaf Wintermann |
32 * @author Olaf Wintermann |
33 * \copyright 2-Clause BSD License |
33 * @copyright 2-Clause BSD License |
34 */ |
34 */ |
35 |
35 |
36 #ifndef UCX_PROPERTIES_H |
36 #ifndef UCX_PROPERTIES_H |
37 #define UCX_PROPERTIES_H |
37 #define UCX_PROPERTIES_H |
38 |
38 |
114 CX_PROPERTIES_INCOMPLETE_DATA, |
114 CX_PROPERTIES_INCOMPLETE_DATA, |
115 /** |
115 /** |
116 * Not used as a status and never returned by any function. |
116 * Not used as a status and never returned by any function. |
117 * |
117 * |
118 * You can use this enumerator to check for all "good" status results |
118 * You can use this enumerator to check for all "good" status results |
119 * by checking if the status is less than \c CX_PROPERTIES_OK. |
119 * by checking if the status is less than @c CX_PROPERTIES_OK. |
120 * |
120 * |
121 * A "good" status means, that you can refill data and continue parsing. |
121 * A "good" status means, that you can refill data and continue parsing. |
122 */ |
122 */ |
123 CX_PROPERTIES_OK, |
123 CX_PROPERTIES_OK, |
124 /** |
124 /** |
125 * Input buffer is \c NULL. |
125 * Input buffer is @c NULL. |
126 */ |
126 */ |
127 CX_PROPERTIES_NULL_INPUT, |
127 CX_PROPERTIES_NULL_INPUT, |
128 /** |
128 /** |
129 * The line contains a delimiter, but no key. |
129 * The line contains a delimiter, but no key. |
130 */ |
130 */ |
201 * |
201 * |
202 * @param prop the properties interface that wants to sink a k/v-pair |
202 * @param prop the properties interface that wants to sink a k/v-pair |
203 * @param sink the sink |
203 * @param sink the sink |
204 * @param key the key |
204 * @param key the key |
205 * @param value the value |
205 * @param value the value |
206 * @return zero on success, non-zero when sinking the k/v-pair failed |
206 * @retval zero success |
|
207 * @retval non-zero sinking the k/v-pair failed |
207 */ |
208 */ |
208 cx_attr_nonnull |
209 cx_attr_nonnull |
209 typedef int(*cx_properties_sink_func)( |
210 typedef int(*cx_properties_sink_func)( |
210 CxProperties *prop, |
211 CxProperties *prop, |
211 CxPropertiesSink *sink, |
212 CxPropertiesSink *sink, |
239 |
240 |
240 /** |
241 /** |
241 * A function that reads data from a source. |
242 * A function that reads data from a source. |
242 * |
243 * |
243 * When the source is depleted, implementations SHALL provide an empty |
244 * When the source is depleted, implementations SHALL provide an empty |
244 * string in the \p target and return zero. |
245 * string in the @p target and return zero. |
245 * A non-zero return value is only permitted in case of an error. |
246 * A non-zero return value is only permitted in case of an error. |
246 * |
247 * |
247 * The meaning of the optional parameters is implementation-dependent. |
248 * The meaning of the optional parameters is implementation-dependent. |
248 * |
249 * |
249 * @param prop the properties interface that wants to read from the source |
250 * @param prop the properties interface that wants to read from the source |
250 * @param src the source |
251 * @param src the source |
251 * @param target a string buffer where the read data shall be stored |
252 * @param target a string buffer where the read data shall be stored |
252 * @return zero on success, non-zero when reading data failed |
253 * @retval zero success |
|
254 * @retval non-zero reading the data failed |
253 */ |
255 */ |
254 cx_attr_nonnull |
256 cx_attr_nonnull |
255 typedef int(*cx_properties_read_func)( |
257 typedef int(*cx_properties_read_func)( |
256 CxProperties *prop, |
258 CxProperties *prop, |
257 CxPropertiesSource *src, |
259 CxPropertiesSource *src, |
261 /** |
263 /** |
262 * A function that may initialize additional memory for the source. |
264 * A function that may initialize additional memory for the source. |
263 * |
265 * |
264 * @param prop the properties interface that wants to read from the source |
266 * @param prop the properties interface that wants to read from the source |
265 * @param src the source |
267 * @param src the source |
266 * @return zero when initialization was successful, non-zero otherwise |
268 * @retval zero initialization was successful |
|
269 * @retval non-zero otherwise |
267 */ |
270 */ |
268 cx_attr_nonnull |
271 cx_attr_nonnull |
269 typedef int(*cx_properties_read_init_func)( |
272 typedef int(*cx_properties_read_init_func)( |
270 CxProperties *prop, |
273 CxProperties *prop, |
271 CxPropertiesSource *src |
274 CxPropertiesSource *src |
327 void cxPropertiesInit(CxProperties *prop, CxPropertiesConfig config); |
330 void cxPropertiesInit(CxProperties *prop, CxPropertiesConfig config); |
328 |
331 |
329 /** |
332 /** |
330 * Destroys the properties interface. |
333 * Destroys the properties interface. |
331 * |
334 * |
332 * \note Even when you are certain that you did not use the interface in a |
335 * @note Even when you are certain that you did not use the interface in a |
333 * way that caused a memory allocation, you should call this function anyway. |
336 * way that caused a memory allocation, you should call this function anyway. |
334 * Future versions of the library might add features that need additional memory |
337 * Future versions of the library might add features that need additional memory |
335 * and you really don't want to search the entire code where you might need |
338 * and you really don't want to search the entire code where you might need |
336 * add call to this function. |
339 * add call to this function. |
337 * |
340 * |
356 } |
359 } |
357 |
360 |
358 /** |
361 /** |
359 * Initialize a properties parser with the default configuration. |
362 * Initialize a properties parser with the default configuration. |
360 * |
363 * |
361 * @param prop the properties interface |
364 * @param prop (@c CxProperties*) the properties interface |
362 * @see cxPropertiesInit() |
365 * @see cxPropertiesInit() |
363 */ |
366 */ |
364 #define cxPropertiesInitDefault(prop) \ |
367 #define cxPropertiesInitDefault(prop) \ |
365 cxPropertiesInit(prop, cx_properties_config_default) |
368 cxPropertiesInit(prop, cx_properties_config_default) |
366 |
369 |
379 * an allocation of a new buffer and copying the previous contents. |
382 * an allocation of a new buffer and copying the previous contents. |
380 * |
383 * |
381 * @param prop the properties interface |
384 * @param prop the properties interface |
382 * @param buf a pointer to the data |
385 * @param buf a pointer to the data |
383 * @param len the length of the data |
386 * @param len the length of the data |
384 * @return non-zero when a memory allocation was necessary but failed |
387 * @retval zero success |
|
388 * @retval non-zero a memory allocation was necessary but failed |
385 * @see cxPropertiesFill() |
389 * @see cxPropertiesFill() |
386 */ |
390 */ |
387 cx_attr_nonnull |
391 cx_attr_nonnull |
388 cx_attr_access_r(2, 3) |
392 cx_attr_access_r(2, 3) |
389 int cxPropertiesFilln( |
393 int cxPropertiesFilln( |
435 * the additional data is appended - inevitably leading to |
439 * the additional data is appended - inevitably leading to |
436 * an allocation of a new buffer and copying the previous contents. |
440 * an allocation of a new buffer and copying the previous contents. |
437 * |
441 * |
438 * @param prop the properties interface |
442 * @param prop the properties interface |
439 * @param str the text to fill in |
443 * @param str the text to fill in |
440 * @return non-zero when a memory allocation was necessary but failed |
444 * @retval zero success |
|
445 * @retval non-zero a memory allocation was necessary but failed |
441 * @see cxPropertiesFilln() |
446 * @see cxPropertiesFilln() |
442 */ |
447 */ |
443 #define cxPropertiesFill(prop, str) _Generic((str), \ |
448 #define cxPropertiesFill(prop, str) _Generic((str), \ |
444 cxstring: cx_properties_fill_cxstr, \ |
449 cxstring: cx_properties_fill_cxstr, \ |
445 cxmutstr: cx_properties_fill_mutstr, \ |
450 cxmutstr: cx_properties_fill_mutstr, \ |
503 * If no more key/value-pairs are found, #CX_PROPERTIES_NO_DATA is returned. |
508 * If no more key/value-pairs are found, #CX_PROPERTIES_NO_DATA is returned. |
504 * |
509 * |
505 * When an incomplete line is encountered, #CX_PROPERTIES_INCOMPLETE_DATA is |
510 * When an incomplete line is encountered, #CX_PROPERTIES_INCOMPLETE_DATA is |
506 * returned, and you can add more data with #cxPropertiesFill(). |
511 * returned, and you can add more data with #cxPropertiesFill(). |
507 * |
512 * |
508 * \remark The incomplete line will be stored in an internal buffer, which is |
513 * @remark The incomplete line will be stored in an internal buffer, which is |
509 * allocated on the heap, by default. If you want to avoid allocations, |
514 * allocated on the heap, by default. If you want to avoid allocations, |
510 * you can specify sufficient space with cxPropertiesUseStack() after |
515 * you can specify sufficient space with cxPropertiesUseStack() after |
511 * initialization with cxPropertiesInit(). |
516 * initialization with cxPropertiesInit(). |
512 * |
517 * |
513 * \attention The returned strings will point into a buffer that might not be |
518 * @attention The returned strings will point into a buffer that might not be |
514 * available later. It is strongly recommended to copy the strings for further |
519 * available later. It is strongly recommended to copy the strings for further |
515 * use. |
520 * use. |
516 * |
521 * |
517 * @param prop the properties interface |
522 * @param prop the properties interface |
518 * @param key a pointer to the cxstring that shall contain the property name |
523 * @param key a pointer to the cxstring that shall contain the property name |
519 * @param value a pointer to the cxstring that shall contain the property value |
524 * @param value a pointer to the cxstring that shall contain the property value |
520 * @return the status code as defined above |
525 * @retval CX_PROPERTIES_NO_ERROR (zero) a key/value pair was found |
521 * @see cxPropertiesFill() |
526 * @retval CX_PROPERTIES_NO_DATA there is no (more) data in the input buffer |
|
527 * @retval CX_PROPERTIES_INCOMPLETE_DATA the data in the input buffer is incomplete |
|
528 * (fill more data and try again) |
|
529 * @retval CX_PROPERTIES_NULL_INPUT the input buffer was never filled |
|
530 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
|
531 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
|
532 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
522 */ |
533 */ |
523 cx_attr_nonnull |
534 cx_attr_nonnull |
524 cx_attr_nodiscard |
535 cx_attr_nodiscard |
525 CxPropertiesStatus cxPropertiesNext( |
536 CxPropertiesStatus cxPropertiesNext( |
526 CxProperties *prop, |
537 CxProperties *prop, |
532 * Creates a properties sink for an UCX map. |
543 * Creates a properties sink for an UCX map. |
533 * |
544 * |
534 * The values stored in the map will be pointers to strings allocated |
545 * The values stored in the map will be pointers to strings allocated |
535 * by #cx_strdup_a(). |
546 * by #cx_strdup_a(). |
536 * The default stdlib allocator will be used, unless you specify a custom |
547 * The default stdlib allocator will be used, unless you specify a custom |
537 * allocator in the optional \c data of the sink. |
548 * allocator in the optional @c data of the sink. |
538 * |
549 * |
539 * @param map the map that shall consume the k/v-pairs. |
550 * @param map the map that shall consume the k/v-pairs. |
540 * @return the sink |
551 * @return the sink |
541 * @see cxPropertiesLoad() |
552 * @see cxPropertiesLoad() |
542 */ |
553 */ |
608 * The other result codes apply, according to their description. |
619 * The other result codes apply, according to their description. |
609 * |
620 * |
610 * @param prop the properties interface |
621 * @param prop the properties interface |
611 * @param sink the sink |
622 * @param sink the sink |
612 * @param source the source |
623 * @param source the source |
613 * @return the status of the last operation |
624 * @retval CX_PROPERTIES_NO_ERROR (zero) a key/value pair was found |
|
625 * @retval CX_PROPERTIES_READ_INIT_FAILED initializing the source failed |
|
626 * @retval CX_PROPERTIES_READ_FAILED reading from the source failed |
|
627 * @retval CX_PROPERTIES_SINK_FAILED sinking the properties into the sink failed |
|
628 * @retval CX_PROPERTIES_NO_DATA the source did not provide any key/value pairs |
|
629 * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key |
|
630 * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter |
|
631 * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed |
614 */ |
632 */ |
615 cx_attr_nonnull |
633 cx_attr_nonnull |
616 CxPropertiesStatus cxPropertiesLoad( |
634 CxPropertiesStatus cxPropertiesLoad( |
617 CxProperties *prop, |
635 CxProperties *prop, |
618 CxPropertiesSink sink, |
636 CxPropertiesSink sink, |