/* * Copyright (C) 2010 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /** * @defgroup settings settings * @{ @ingroup utils */ #ifndef SETTINGS_H_ #define SETTINGS_H_ typedef struct settings_t settings_t; #include "utils.h" #include "collections/enumerator.h" /** * Convert a string value returned by a key/value enumerator to a boolean. * * @see settings_t.create_key_value_enumerator() * @see settings_t.get_bool() * @param value the string value * @param def the default value, if value is NULL or invalid */ bool settings_value_as_bool(char *value, bool def); /** * Convert a string value returned by a key/value enumerator to an integer. * * @see settings_t.create_key_value_enumerator() * @see settings_t.get_int() * @param value the string value * @param def the default value, if value is NULL or invalid */ int settings_value_as_int(char *value, int def); /** * Convert a string value returned by a key/value enumerator to a double. * * @see settings_t.create_key_value_enumerator() * @see settings_t.get_double() * @param value the string value * @param def the default value, if value is NULL or invalid */ double settings_value_as_double(char *value, double def); /** * Convert a string value returned by a key/value enumerator to a time value. * * @see settings_t.create_key_value_enumerator() * @see settings_t.get_time() * @param value the string value * @param def the default value, if value is NULL or invalid */ u_int32_t settings_value_as_time(char *value, u_int32_t def); /** * Generic configuration options read from a config file. * * The syntax is quite simple: * @code * settings := (section|keyvalue)* * section := name { settings } * keyvalue := key = value\n * @endcode * E.g.: * @code a = b section-one { somevalue = asdf subsection { othervalue = xxx } yetanother = zz } section-two { } @endcode * * The values are accessed using the get() functions using dotted keys, e.g. * section-one.subsection.othervalue * * Currently only a limited set of printf format specifiers are supported * (namely %s, %d and %N, see implementation for details). * * \section includes Including other files * Other files can be included, using the include statement e.g. * @code * include /somepath/subconfig.conf * @endcode * Shell patterns like *.conf are possible. * * If the path is relative, the directory of the file containing the include * statement is used as base. * * Sections loaded from included files extend previously loaded sections, * already existing values are replaced. * * All settings included from files are added relative to the section the * include statement is in. * * The following files result in the same final config as above: * * @code a = b section-one { somevalue = before include include include.conf } include two.conf @endcode * include.conf * @code somevalue = asdf subsection { othervalue = yyy } yetanother = zz @endcode * two.conf * @code section-one { subsection { othervalue = xxx } } section-two { } @endcode */ struct settings_t { /** * Get a settings value as a string. * * @param key key including sections, printf style format * @param def value returned if key not found * @param ... argument list for key * @return value pointing to internal string */ char* (*get_str)(settings_t *this, char *key, char *def, ...); /** * Get a boolean yes|no, true|false value. * * @param key key including sections, printf style format * @param def value returned if key not found * @param ... argument list for key * @return value of the key */ bool (*get_bool)(settings_t *this, char *key, bool def, ...); /** * Get an integer value. * * @param key key including sections, printf style format * @param def value returned if key not found * @param ... argument list for key * @return value of the key */ int (*get_int)(settings_t *this, char *key, int def, ...); /** * Get an double value. * * @param key key including sections, printf style format * @param def value returned if key not found * @param ... argument list for key * @return value of the key */ double (*get_double)(settings_t *this, char *key, double def, ...); /** * Get a time value. * * @param key key including sections, printf style format * @param def value returned if key not found * @param ... argument list for key * @return value of the key (in seconds) */ u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...); /** * Set a string value. * * @param key key including sections, printf style format * @param value value to set (gets cloned) * @param ... argument list for key */ void (*set_str)(settings_t *this, char *key, char *value, ...); /** * Set a boolean value. * * @param key key including sections, printf style format * @param value value to set * @param ... argument list for key */ void (*set_bool)(settings_t *this, char *key, bool value, ...); /** * Set an integer value. * * @param key key including sections, printf style format * @param value value to set * @param ... argument list for key */ void (*set_int)(settings_t *this, char *key, int value, ...); /** * Set an double value. * * @param key key including sections, printf style format * @param value value to set * @param ... argument list for key */ void (*set_double)(settings_t *this, char *key, double value, ...); /** * Set a time value. * * @param key key including sections, printf style format * @param def value to set * @param ... argument list for key */ void (*set_time)(settings_t *this, char *key, u_int32_t value, ...); /** * Set a default for string value. * * @param key key including sections, printf style format * @param def value to set if unconfigured * @param ... argument list for key * @return TRUE if a new default value for key has been set */ bool (*set_default_str)(settings_t *this, char *key, char *value, ...); /** * Create an enumerator over subsection names of a section. * * @param section section including parents, printf style format * @param ... argument list for key * @return enumerator over subsection names */ enumerator_t* (*create_section_enumerator)(settings_t *this, char *section, ...); /** * Create an enumerator over key/value pairs in a section. * * @param section section name to list key/value pairs of, printf style * @param ... argument list for section * @return enumerator over (char *key, char *value) */ enumerator_t* (*create_key_value_enumerator)(settings_t *this, char *section, ...); /** * Add a fallback for the given section. * * Example: When the fallback 'section-two' is configured for * 'section-one.two' any failed lookup for a section or key in * 'section-one.two' will result in a lookup for the same section/key * in 'section-two'. * * @note Lookups are depth-first and currently strictly top-down. * For instance, if app.sec had lib1.sec as fallback and lib1 had lib2 as * fallback the keys/sections in lib2.sec would not be considered. But if * app had lib3 as fallback the contents of lib3.sec would (as app is passed * during the initial lookup). In the last example the order during * enumerations would be app.sec, lib1.sec, lib3.sec. * * @note Additional arguments will be applied to both section format * strings so they must be compatible. * * @param section section for which a fallback is configured, printf style * @param fallback fallback section, printf style * @param ... argument list for section and fallback */ void (*add_fallback)(settings_t *this, const char *section, const char *fallback, ...); /** * Load settings from the files matching the given pattern. * * If merge is TRUE, existing sections are extended, existing values * replaced, by those found in the loaded files. If it is FALSE, existing * sections are purged before reading the new config. * * @note If any of the files matching the pattern fails to load, no settings * are added at all. So, it's all or nothing. * * @param pattern file pattern * @param merge TRUE to merge config with existing values * @return TRUE, if settings were loaded successfully */ bool (*load_files)(settings_t *this, char *pattern, bool merge); /** * Load settings from the files matching the given pattern. * * If merge is TRUE, existing sections are extended, existing values * replaced, by those found in the loaded files. If it is FALSE, existing * sections are purged before reading the new config. * * All settings are loaded relative to the given section. The section is * created, if it does not yet exist. * * @note If any of the files matching the pattern fails to load, no settings * are added at all. So, it's all or nothing. * * @param pattern file pattern * @param merge TRUE to merge config with existing values * @param section section name of parent section, printf style * @param ... argument list for section * @return TRUE, if settings were loaded successfully */ bool (*load_files_section)(settings_t *this, char *pattern, bool merge, char *section, ...); /** * Destroy a settings instance. */ void (*destroy)(settings_t *this); }; /** * Load settings from a file. * * @param file file to read settings from, NULL for default * @return settings object */ settings_t *settings_create(char *file); #endif /** SETTINGS_H_ @}*/