--- a/src/cx/properties.h Thu Oct 10 18:40:27 2024 +0200 +++ b/src/cx/properties.h Sat Oct 12 19:34:19 2024 +0200 @@ -38,6 +38,7 @@ #include "common.h" #include "string.h" +#include "array_list.h" struct cx_properties_config_s { /** @@ -50,7 +51,7 @@ * The character, when appearing at the end of a line, continues that line. * This is '\' by default. */ - char continuation; + // char continuation; // TODO: line continuation in properties /** * The first comment character. @@ -104,6 +105,18 @@ * Input buffer is \c NULL. */ CX_PROPERTIES_NULL_INPUT, + /** + * The line contains a delimiter, but no key. + */ + CX_PROPERTIES_INVALID_EMPTY_KEY, + /** + * The line contains data, but no delimiter. + */ + CX_PROPERTIES_INVALID_MISSING_DELIMITER, + /** + * More internal buffer was needed, but could not be allocated. + */ + CX_PROPERTIES_BUFFER_ALLOC_FAILED, }; /** @@ -121,14 +134,34 @@ const char *text; /** - * Length of the text buffer. + * Size of the text buffer. */ - size_t text_len; + size_t text_size; /** * Position in the text buffer. */ size_t text_pos; + + /** + * Temporary internal buffer. + */ + char *buf; + + /** + * Size of the internal buffer. + */ + size_t buf_size; + + /** + * Capacity of the internal buffer. + */ + size_t buf_capacity; + + /** + * Internal flags. + */ + int flags; }; /** @@ -138,20 +171,28 @@ /** - * Initialize a properties parser. + * Initialize a properties interface. * * @param prop the properties interface * @param config the properties configuration * @see cxPropertiesInitDefault() */ - __attribute__((__nonnull__)) -static inline void cxPropertiesInit( - CxProperties *prop, - CxPropertiesConfig config -) { - prop->config = config; - prop->text = NULL; - } +__attribute__((__nonnull__)) +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 + * 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 + * add call to this function. + * + * @param prop the properties interface + */ +__attribute__((__nonnull__)) +void cxPropertiesDestroy(CxProperties *prop); /** * Initialize a properties parser with the default configuration. @@ -173,35 +214,72 @@ * @param len the length of the data */ __attribute__((__nonnull__)) -static inline void cxPropertiesInput( +void cxPropertiesInput( CxProperties *prop, - const void *buf, + const char *buf, size_t len -) { - prop->text = buf; - prop->text_len = len; - prop->text_pos = 0; -} +); + +/** + * Sets a new input buffer after copying the current unprocessed data + * to a temporary buffer. + * + * This temporary buffer is allocated on the heap, unless you specified + * a buffer on the stack with #cxPropertiesUseStack(). + * In that case, the stack buffer is used, until the capacity is not sufficient + * anymore. + * + * When this function is called without any unprocessed data that needs to be + * copied, it behaves exactly as #cxPropertiesInput(). + * + * @param prop the properties interface + * @param buf a pointer to data + * @param len the length of the data + * @return non-zero when a memory allocation was necessary but failed + */ +__attribute__((__nonnull__)) +int cxPropertiesFill( + CxProperties *prop, + const char *buf, + size_t len +); + +/** + * Specifies stack memory that shall be used by #cxPropertiesFill(). + * + * @param prop the properties interface + * @param buf a pointer to stack memory + * @param capacity the capacity of the stack memory + */ +void cxPropertiesUseStack( + CxProperties *prop, + char *buf, + size_t capacity +); /** * Retrieves the next key/value-pair. * - * This function returns zero as long as there are key/value-pairs - * found. If no more key/value-pairs are found, #CX_PROPERTIES_NO_DATA - * is returned. You may refill the input buffer with cxPropertiesInput(). + * This function returns zero as long as there are key/value-pairs found. + * If no more key/value-pairs are found, #CX_PROPERTIES_NO_DATA is returned. * - * When an invalid line is encountered, #CX_PROPERTIES_INVALID_LINE is returned - * and the position of the input buffer will be the start of the affected line. + * When an incomplete line is encountered, #CX_PROPERTIES_INCOMPLETE_DATA is + * returned and the position of the input buffer will be the start of the + * affected line. You can then add more data with #cxPropertiesFill(). + * + * \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 name a pointer to the cxstring that shall contain the property name + * @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 Nonzero, if a key/value-pair was successfully retrieved - * @see ucx_properties_fill() + * @return the status code as defined above + * @see cxPropertiesFill() */ enum cx_properties_status cxPropertiesNext( CxProperties *prop, - cxstring *name, + cxstring *key, cxstring *value );