/** * @file config.h * @brief Simple key=value configuration file parser. * * Parses configuration files with one key=value pair per line. * Lines starting with '#' are comments. Blank lines are ignored. * Repeated keys are allowed (used for list-valued settings like * trustList). */ #ifndef DISCOVERY_CONFIG_H #define DISCOVERY_CONFIG_H #include /** * @brief A single key=value entry from a config file. * * Both key and value are heap-allocated, null-terminated strings * with leading/trailing whitespace trimmed. */ typedef struct { char *key; char *value; } ConfigEntry; /** * @brief A parsed configuration file. * * Holds a dynamic array of ConfigEntry items. Duplicate keys are * allowed (used for list-valued settings like trustList). */ typedef struct { ConfigEntry *entries; size_t count; size_t capacity; } Config; /** * @brief Parses a configuration file into a Config structure. * * Each non-blank, non-comment line must contain '=' separating key * and value. Whitespace is trimmed around both key and value. * * @param path Path to the configuration file. * @param cfg Output: the parsed configuration. Must be freed * with configFree() when no longer needed. * @return 0 on success, -1 on error (logged via UA_LOG_ERROR). */ int configLoad (const char *path, Config *cfg); /** * @brief Looks up a single-valued key. * * Returns the value of the first entry matching @p key, or NULL * if the key is not present. * * @param cfg The parsed configuration. * @param key The key to search for. * @return The value string (owned by cfg), or NULL. */ const char *configGet (const Config *cfg, const char *key); /** * @brief Looks up a required single-valued key. * * Like configGet(), but logs a FATAL error and returns NULL when * the key is missing. * * @param cfg The parsed configuration. * @param key The key to search for. * @param program Program name (for error messages). * @return The value string (owned by cfg), or NULL if missing. */ const char *configRequire (const Config *cfg, const char *key, const char *program); /** * @brief Looks up a required integer-valued key. * * Parses the value of @p key as an integer. If the key is * missing or the value is not a valid integer, logs a FATAL * error and returns -1. * * @param cfg The parsed configuration. * @param key The key to search for. * @param program Program name (for error messages). * @return The parsed integer, or -1 on error. */ int configRequireInt (const Config *cfg, const char *key, const char *program); /** * @brief Collects all values for a repeated key. * * Allocates an array of char* pointers to the values stored * in @p cfg. The caller must free the array itself (but not * the strings, which are owned by cfg). * * @param cfg The parsed configuration. * @param key The key to collect (e.g. "trustList"). * @param out Output: heap-allocated array of string pointers. * Set to NULL if the key is not present. * @param size Output: number of entries in @p out. */ void configGetAll (const Config *cfg, const char *key, char ***out, size_t *size); /** * @brief Frees all memory owned by a Config structure. * * After this call the Config is zeroed and must not be used * unless configLoad() is called again. * * @param cfg The configuration to free. */ void configFree (Config *cfg); #endif /* DISCOVERY_CONFIG_H */