--- a/ucx/cx/properties.h Sun Feb 16 17:38:07 2025 +0100 +++ b/ucx/cx/properties.h Tue Feb 25 21:12:11 2025 +0100 @@ -26,11 +26,11 @@ * POSSIBILITY OF SUCH DAMAGE. */ /** - * \file properties.h - * \brief Interface for parsing data from properties files. - * \author Mike Becker - * \author Olaf Wintermann - * \copyright 2-Clause BSD License + * @file properties.h + * @brief Interface for parsing data from properties files. + * @author Mike Becker + * @author Olaf Wintermann + * @copyright 2-Clause BSD License */ #ifndef UCX_PROPERTIES_H @@ -59,12 +59,6 @@ char delimiter; /** - * The character, when appearing at the end of a line, continues that line. - * This is '\' by default. - */ - // char continuation; // TODO: line continuation in properties - - /** * The first comment character. * This is '#' by default. */ @@ -81,6 +75,15 @@ * This is not set by default. */ char comment3; + + /* + * The character, when appearing at the end of a line, continues that line. + * This is '\' by default. + */ + /** + * Reserved for future use. + */ + char continuation; }; /** @@ -91,6 +94,7 @@ /** * Default properties configuration. */ +cx_attr_export extern const CxPropertiesConfig cx_properties_config_default; /** @@ -116,13 +120,13 @@ * Not used as a status and never returned by any function. * * You can use this enumerator to check for all "good" status results - * by checking if the status is less than \c CX_PROPERTIES_OK. + * by checking if the status is less than @c CX_PROPERTIES_OK. * * A "good" status means, that you can refill data and continue parsing. */ CX_PROPERTIES_OK, /** - * Input buffer is \c NULL. + * Input buffer is @c NULL. */ CX_PROPERTIES_NULL_INPUT, /** @@ -203,7 +207,8 @@ * @param sink the sink * @param key the key * @param value the value - * @return zero on success, non-zero when sinking the k/v-pair failed + * @retval zero success + * @retval non-zero sinking the k/v-pair failed */ cx_attr_nonnull typedef int(*cx_properties_sink_func)( @@ -241,7 +246,7 @@ * A function that reads data from a source. * * When the source is depleted, implementations SHALL provide an empty - * string in the \p target and return zero. + * string in the @p target and return zero. * A non-zero return value is only permitted in case of an error. * * The meaning of the optional parameters is implementation-dependent. @@ -249,7 +254,8 @@ * @param prop the properties interface that wants to read from the source * @param src the source * @param target a string buffer where the read data shall be stored - * @return zero on success, non-zero when reading data failed + * @retval zero success + * @retval non-zero reading the data failed */ cx_attr_nonnull typedef int(*cx_properties_read_func)( @@ -263,7 +269,8 @@ * * @param prop the properties interface that wants to read from the source * @param src the source - * @return zero when initialization was successful, non-zero otherwise + * @retval zero initialization was successful + * @retval non-zero otherwise */ cx_attr_nonnull typedef int(*cx_properties_read_init_func)( @@ -324,12 +331,13 @@ * @see cxPropertiesInitDefault() */ cx_attr_nonnull +cx_attr_export void cxPropertiesInit(CxProperties *prop, CxPropertiesConfig config); /** * Destroys the properties interface. * - * \note Even when you are certain that you did not use the interface in a + * @note Even when you are certain that you did not use the interface in a * way that caused a memory allocation, you should call this function anyway. * Future versions of the library might add features that need additional memory * and you really don't want to search the entire code where you might need @@ -338,6 +346,7 @@ * @param prop the properties interface */ cx_attr_nonnull +cx_attr_export void cxPropertiesDestroy(CxProperties *prop); /** @@ -358,7 +367,7 @@ /** * Initialize a properties parser with the default configuration. * - * @param prop the properties interface + * @param prop (@c CxProperties*) the properties interface * @see cxPropertiesInit() */ #define cxPropertiesInitDefault(prop) \ @@ -381,11 +390,13 @@ * @param prop the properties interface * @param buf a pointer to the data * @param len the length of the data - * @return non-zero when a memory allocation was necessary but failed + * @retval zero success + * @retval non-zero a memory allocation was necessary but failed * @see cxPropertiesFill() */ cx_attr_nonnull cx_attr_access_r(2, 3) +cx_attr_export int cxPropertiesFilln( CxProperties *prop, const char *buf, @@ -437,7 +448,8 @@ * * @param prop the properties interface * @param str the text to fill in - * @return non-zero when a memory allocation was necessary but failed + * @retval zero success + * @retval non-zero a memory allocation was necessary but failed * @see cxPropertiesFilln() */ #define cxPropertiesFill(prop, str) _Generic((str), \ @@ -490,6 +502,7 @@ * @param capacity the capacity of the stack memory */ cx_attr_nonnull +cx_attr_export void cxPropertiesUseStack( CxProperties *prop, char *buf, @@ -505,23 +518,30 @@ * When an incomplete line is encountered, #CX_PROPERTIES_INCOMPLETE_DATA is * returned, and you can add more data with #cxPropertiesFill(). * - * \remark The incomplete line will be stored in an internal buffer, which is + * @remark The incomplete line will be stored in an internal buffer, which is * allocated on the heap, by default. If you want to avoid allocations, * you can specify sufficient space with cxPropertiesUseStack() after * initialization with cxPropertiesInit(). * - * \attention The returned strings will point into a buffer that might not be + * @attention The returned strings will point into a buffer that might not be * available later. It is strongly recommended to copy the strings for further * use. * * @param prop the properties interface * @param key a pointer to the cxstring that shall contain the property name * @param value a pointer to the cxstring that shall contain the property value - * @return the status code as defined above - * @see cxPropertiesFill() + * @retval CX_PROPERTIES_NO_ERROR (zero) a key/value pair was found + * @retval CX_PROPERTIES_NO_DATA there is no (more) data in the input buffer + * @retval CX_PROPERTIES_INCOMPLETE_DATA the data in the input buffer is incomplete + * (fill more data and try again) + * @retval CX_PROPERTIES_NULL_INPUT the input buffer was never filled + * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key + * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter + * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed */ cx_attr_nonnull cx_attr_nodiscard +cx_attr_export CxPropertiesStatus cxPropertiesNext( CxProperties *prop, cxstring *key, @@ -534,7 +554,7 @@ * The values stored in the map will be pointers to strings allocated * by #cx_strdup_a(). * The default stdlib allocator will be used, unless you specify a custom - * allocator in the optional \c data of the sink. + * allocator in the optional @c data of the sink. * * @param map the map that shall consume the k/v-pairs. * @return the sink @@ -542,6 +562,7 @@ */ cx_attr_nonnull cx_attr_nodiscard +cx_attr_export CxPropertiesSink cxPropertiesMapSink(CxMap *map); /** @@ -552,6 +573,7 @@ * @see cxPropertiesLoad() */ cx_attr_nodiscard +cx_attr_export CxPropertiesSource cxPropertiesStringSource(cxstring str); /** @@ -565,6 +587,7 @@ cx_attr_nonnull cx_attr_nodiscard cx_attr_access_r(1, 2) +cx_attr_export CxPropertiesSource cxPropertiesCstrnSource(const char *str, size_t len); /** @@ -580,6 +603,7 @@ cx_attr_nonnull cx_attr_nodiscard cx_attr_cstr_arg(1) +cx_attr_export CxPropertiesSource cxPropertiesCstrSource(const char *str); /** @@ -594,6 +618,7 @@ cx_attr_nonnull cx_attr_nodiscard cx_attr_access_r(1) +cx_attr_export CxPropertiesSource cxPropertiesFileSource(FILE *file, size_t chunk_size); @@ -605,14 +630,28 @@ * the return value will be #CX_PROPERTIES_NO_ERROR. * When the source was consumed but no k/v-pairs were found, the return value * will be #CX_PROPERTIES_NO_DATA. + * In case the source data ends unexpectedly, the #CX_PROPERTIES_INCOMPLETE_DATA + * is returned. In that case you should call this function again with the same + * sink and either an updated source or the same source if the source is able to + * yield the missing data. + * * The other result codes apply, according to their description. * * @param prop the properties interface * @param sink the sink * @param source the source - * @return the status of the last operation + * @retval CX_PROPERTIES_NO_ERROR (zero) a key/value pair was found + * @retval CX_PROPERTIES_READ_INIT_FAILED initializing the source failed + * @retval CX_PROPERTIES_READ_FAILED reading from the source failed + * @retval CX_PROPERTIES_SINK_FAILED sinking the properties into the sink failed + * @retval CX_PROPERTIES_NO_DATA the source did not provide any key/value pairs + * @retval CX_PROPERTIES_INCOMPLETE_DATA the source did not provide enough data + * @retval CX_PROPERTIES_INVALID_EMPTY_KEY the properties data contains an illegal empty key + * @retval CX_PROPERTIES_INVALID_MISSING_DELIMITER the properties data contains a line without delimiter + * @retval CX_PROPERTIES_BUFFER_ALLOC_FAILED an internal allocation was necessary but failed */ cx_attr_nonnull +cx_attr_export CxPropertiesStatus cxPropertiesLoad( CxProperties *prop, CxPropertiesSink sink,