PengZheng commented on code in PR #470: URL: https://github.com/apache/celix/pull/470#discussion_r1390163874
########## libs/utils/include/celix_properties.h: ########## @@ -17,86 +17,509 @@ * under the License. */ +/** + * @file celix_properties.h + * @brief Header file for the Celix Properties API. + * + * The Celix Properties API provides a means for storing and manipulating key-value pairs, called properties, + * which can be used to store configuration data or metadata for a service, component, or framework configuration. + * Functions are provided for creating and destroying property sets, loading and storing properties from/to a file + * or stream, and setting, getting, and unsetting individual properties. There are also functions for converting + * property values to various types (e.g. long, bool, double) and for iterating over the properties in a set. + * + * Supported property value types include: + * - string (char*) + * - long + * - double + * - bool + * - celix_version_t* + */ + #ifndef CELIX_PROPERTIES_H_ #define CELIX_PROPERTIES_H_ #include <stdio.h> -#include <stdbool.h> #include "celix_cleanup.h" #include "celix_compiler.h" #include "celix_errno.h" #include "celix_utils_export.h" +#include "celix_version.h" #ifdef __cplusplus extern "C" { #endif -typedef struct hashMap celix_properties_t; //opaque struct, TODO try to make this a celix_properties struct +/** + * @brief celix_properties_t is a type that represents a set of key-value pairs called properties. + * + * @note Not thread safe. + */ +typedef struct celix_properties celix_properties_t; + +/** + * @brief Enum representing the possible types of a property value. + */ +typedef enum celix_properties_value_type { + CELIX_PROPERTIES_VALUE_TYPE_UNSET = 0, /**< Property value is not set. */ + CELIX_PROPERTIES_VALUE_TYPE_STRING = 1, /**< Property value is a string. */ + CELIX_PROPERTIES_VALUE_TYPE_LONG = 2, /**< Property value is a long integer. */ + CELIX_PROPERTIES_VALUE_TYPE_DOUBLE = 3, /**< Property value is a double. */ + CELIX_PROPERTIES_VALUE_TYPE_BOOL = 4, /**< Property value is a boolean. */ + CELIX_PROPERTIES_VALUE_TYPE_VERSION = 5 /**< Property value is a Celix version. */ +} celix_properties_value_type_e; +/** + * @brief A structure representing a single value entry in a property set. + */ +typedef struct celix_properties_entry { + const char* value; /**< The string value or string representation of a non-string + typed value.*/ + celix_properties_value_type_e valueType; /**< The type of the value of the entry */ + + union { + const char* strValue; /**< The string value of the entry. */ + long longValue; /**< The long integer value of the entry. */ + double doubleValue; /**< The double-precision floating point value of the entry. */ + bool boolValue; /**< The boolean value of the entry. */ + const celix_version_t* versionValue; /**< The Celix version value of the entry. */ + } typed; /**< The typed values of the entry. Only valid if valueType + is not CELIX_PROPERTIES_VALUE_TYPE_UNSET and only the matching + value types should be used. E.g typed.boolValue if valueType is + CELIX_PROPERTIES_VALUE_TYPE_BOOL. */ +} celix_properties_entry_t; + +/** + * @brief Represents an iterator for iterating over the entries in a celix_properties_t object. + */ typedef struct celix_properties_iterator { - //private data - void* _data1; - void* _data2; - void* _data3; - int _data4; - int _data5; -} celix_properties_iterator_t; + /** + * @brief The index of the current iterator. + */ + size_t index; + /** + * @brief The current key. + */ + const char* key; -/********************************************************************************************************************** - ********************************************************************************************************************** - * Updated API - ********************************************************************************************************************** - **********************************************************************************************************************/ + /** + * @brief The current value entry. + */ + celix_properties_entry_t entry; -CELIX_UTILS_EXPORT celix_properties_t* celix_properties_create(void); + /** + * @brief Private data used to implement the iterator. + */ + char _data[56]; +} celix_properties_iterator_t; -CELIX_UTILS_EXPORT void celix_properties_destroy(celix_properties_t *properties); +/** + * @brief Create a new empty property set. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @return A new empty property set. + */ +CELIX_UTILS_EXPORT celix_properties_t* celix_properties_create(); + +/** + * @brief Destroy a property set, freeing all associated resources. + * + * @param[in] properties The property set to destroy. If properties is NULL, this function will do nothing. + */ +CELIX_UTILS_EXPORT void celix_properties_destroy(celix_properties_t* properties); CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_properties_t, celix_properties_destroy) -CELIX_UTILS_EXPORT celix_properties_t* celix_properties_load(const char *filename); +/** + * @brief Load properties from a file. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] filename The name of the file to load properties from. + * @return A property set containing the properties from the file. + * @retval NULL If an error occurred (e.g. file not found). + */ +CELIX_UTILS_EXPORT celix_properties_t* celix_properties_load(const char* filename); -CELIX_UTILS_EXPORT celix_properties_t* celix_properties_loadWithStream(FILE *stream); +/** + * @brief Load properties from a stream. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in,out] stream The stream to load properties from. + * @return A property set containing the properties from the stream. + * @retval NULL If an error occurred (e.g. invalid format). + */ +CELIX_UTILS_EXPORT celix_properties_t* celix_properties_loadWithStream(FILE* stream); -CELIX_UTILS_EXPORT celix_properties_t* celix_properties_loadFromString(const char *input); +/** + * @brief Load properties from a string. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] input The string to load properties from. + * @return A property set containing the properties from the string. + * @retval NULL If an error occurred (e.g. invalid format). + */ +CELIX_UTILS_EXPORT celix_properties_t* celix_properties_loadFromString(const char* input); -CELIX_UTILS_EXPORT void celix_properties_store(celix_properties_t *properties, const char *file, const char *header); +/** + * @brief Store properties to a file. + * + * @note Properties values are always stored as string values, regardless of their actual underlining types. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] properties The property set to store. + * @param[in] file The name of the file to store the properties to. + * @param[in] header An optional - single line - header to write to the file before the properties. + * Will be prefix with a '#' character. + * @return CELIX_SUCCESS if the operation was successful, CELIX_FILE_IO_EXCEPTION if there was an error writing to the + * file. + */ +CELIX_UTILS_EXPORT celix_status_t celix_properties_store(celix_properties_t* properties, + const char* file, + const char* header); -CELIX_UTILS_EXPORT const char* celix_properties_get(const celix_properties_t *properties, const char *key, const char *defaultValue); +/** + * @brief Get the entry for a given key in a property set. + * + * @param[in] properties The property set to search. + * @param[in] key The key to search for. + * @return The entry for the given key, or a NULL if the key is not found. + */ +CELIX_UTILS_EXPORT celix_properties_entry_t* celix_properties_getEntry(const celix_properties_t* properties, + const char* key); -CELIX_UTILS_EXPORT void celix_properties_set(celix_properties_t *properties, const char *key, const char *value); +/** + * @brief Get the value of a property. + * + * @param[in] properties The property set to search. + * @param[in] key The key of the property to get. + * @param[in] defaultValue The value to return if the property is not set. + * @return The value of the property, or the default value if the property is not set. + */ +CELIX_UTILS_EXPORT const char* +celix_properties_get(const celix_properties_t* properties, const char* key, const char* defaultValue); -CELIX_UTILS_EXPORT void celix_properties_setWithoutCopy(celix_properties_t *properties, char *key, char *value); +/** + * @brief Get the type of a property value. + * + * @param[in] properties The property set to search. + * @param[in] key The key of the property to get the type of. + * @return The type of the property value, or CELIX_PROPERTIES_VALUE_TYPE_UNSET if the property is not set. + */ +CELIX_UTILS_EXPORT celix_properties_value_type_e celix_properties_getType(const celix_properties_t* properties, + const char* key); -CELIX_UTILS_EXPORT void celix_properties_unset(celix_properties_t *properties, const char *key); +/** + * @brief Set the value of a property. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] value The value to set the property to. + * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if there was not enough memory to set the entry + * and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL. + */ +CELIX_UTILS_EXPORT celix_status_t celix_properties_set(celix_properties_t* properties, + const char* key, + const char* value); -CELIX_UTILS_EXPORT celix_properties_t* celix_properties_copy(const celix_properties_t *properties); +/** + * @brief Set the value of a property without copying the value string. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. This callee will take ownership of the key, so the key must not be + * used after calling this function. The key should be deallocated with free. + * @param[in] value The value to set the property to. This callee will take ownership of the value, so the value must + * not be used after calling this function. The value should be deallocated with free. + * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if there was not enough memory to set the entry + * and CELIX_ILLEGAL_ARGUMENT if the provided key or value is NULL. + * When CELIX_ENOMEM is returned, the key and value strings are not used and freed by this function. + */ +CELIX_UTILS_EXPORT celix_status_t celix_properties_setWithoutCopy(celix_properties_t* properties, + char* key, + char* value); -CELIX_UTILS_EXPORT long celix_properties_getAsLong(const celix_properties_t *props, const char *key, long defaultValue); -CELIX_UTILS_EXPORT void celix_properties_setLong(celix_properties_t *props, const char *key, long value); +/** + * @brief Get the value of a property as a long integer. + * + * @param[in] properties The property set to search. + * @param[in] key The key of the property to get. + * @param[in] defaultValue The value to return if the property is not set, the value is not a long integer, + * or if the value cannot be converted to a long integer. + * @return The value of the property as a long integer, or the default value if the property is not set, + * the value is not a long integer, or if the value cannot be converted to a long integer. + * If the value is a string, it will be converted to a long integer if possible. + */ +CELIX_UTILS_EXPORT long +celix_properties_getAsLong(const celix_properties_t* properties, const char* key, long defaultValue); -CELIX_UTILS_EXPORT bool celix_properties_getAsBool(const celix_properties_t *props, const char *key, bool defaultValue); -CELIX_UTILS_EXPORT void celix_properties_setBool(celix_properties_t *props, const char *key, bool val); +/** + * @brief Set the value of a property to a long integer. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] value The long value to set the property to. + * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if there was not enough memory to set the entry + * and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL. + */ +CELIX_UTILS_EXPORT celix_status_t celix_properties_setLong(celix_properties_t* properties, const char* key, long value); +/** + * @brief Get the value of a property as a boolean. + * + * @param[in] properties The property set to search. + * @param[in] key The key of the property to get. + * @param[in] defaultValue The value to return if the property is not set, the value is not a boolean, or if the value + * cannot be converted to a boolean. + * @return The value of the property as a boolean, or the default value if the property is not set, the value is not a + * boolean, or if the value cannot be converted to a boolean. If the value is a string, it will be converted + * to a boolean if possible. + */ +CELIX_UTILS_EXPORT bool +celix_properties_getAsBool(const celix_properties_t* properties, const char* key, bool defaultValue); -CELIX_UTILS_EXPORT void celix_properties_setDouble(celix_properties_t *props, const char *key, double val); -CELIX_UTILS_EXPORT double celix_properties_getAsDouble(const celix_properties_t *props, const char *key, double defaultValue); +/** + * @brief Set the value of a property to a boolean. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] val The boolean value to set the property to. + * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if there was not enough memory to set the entry + * and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL. + */ +CELIX_UTILS_EXPORT celix_status_t celix_properties_setBool(celix_properties_t* properties, const char* key, bool val); -CELIX_UTILS_EXPORT int celix_properties_size(const celix_properties_t *properties); +/** + * @brief Set the value of a property to a double. + * + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] val The double value to set the property to. + * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if there was not enough memory to set the entry + * and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL. + */ +CELIX_UTILS_EXPORT celix_status_t celix_properties_setDouble(celix_properties_t* properties, + const char* key, + double val); -CELIX_UTILS_EXPORT celix_properties_iterator_t celix_propertiesIterator_construct(const celix_properties_t *properties); -CELIX_UTILS_EXPORT bool celix_propertiesIterator_hasNext(celix_properties_iterator_t *iter); -CELIX_UTILS_EXPORT const char* celix_propertiesIterator_nextKey(celix_properties_iterator_t *iter); -CELIX_UTILS_EXPORT celix_properties_t* celix_propertiesIterator_properties(celix_properties_iterator_t *iter); +/** + * @brief Get the value of a property as a double. + * + * @param[in] properties The property set to search. + * @param[in] key The key of the property to get. + * @param[in] defaultValue The value to return if the property is not set, the value is not a double, + * or if the value cannot be converted to a double. + * @return The value of the property as a double, or the default value if the property is not set, the value is not + * a double, or if the value cannot be converted to a double. If the value is a string, it will be converted + * to a double if possible. + */ +CELIX_UTILS_EXPORT double +celix_properties_getAsDouble(const celix_properties_t* properties, const char* key, double defaultValue); -#define CELIX_PROPERTIES_FOR_EACH(props, key) _CELIX_PROPERTIES_FOR_EACH(CELIX_UNIQUE_ID(iter), props, key) +/** + * @brief Set the value of a property as a Celix version. + * + * This function will make a copy of the provided celix_version_t object and store it in the property set. + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] version The value to set. The function will make a copy of this object and store it in the property set. + * @return CELIX_SUCCESS if the operation was successful, CELIX_ENOMEM if there was not enough memory to set the entry + * and CELIX_ILLEGAL_ARGUMENT if the provided key is NULL. + */ +CELIX_UTILS_EXPORT celix_status_t celix_properties_setVersion(celix_properties_t* properties, + const char* key, + const celix_version_t* version); -#define _CELIX_PROPERTIES_FOR_EACH(iter, props, key) \ - for(celix_properties_iterator_t iter = celix_propertiesIterator_construct(props); \ - celix_propertiesIterator_hasNext(&iter), (key) = celix_propertiesIterator_nextKey(&iter);) +/** + * @brief Set the value of a property as a Celix version. + * + * This function will store a reference to the provided celix_version_t object in the property set and takes + * ownership of the provided version. + * If the return status is an error, a error message is logged to celix_err. + * + * @param[in] properties The property set to modify. + * @param[in] key The key of the property to set. + * @param[in] version The value to set. The function will store a reference to this object in the property set and + * takes ownership of the provided version. + * Review Comment: `@return` is missing. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@celix.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org