From e94bd6a27148f4fcdf48e2bae85440416900920b Mon Sep 17 00:00:00 2001 From: Michael Carlberg Date: Wed, 27 Jul 2016 02:53:47 +0200 Subject: [PATCH] feat(config): Reference value in environment var This makes it possible to reference env vars from any config parameter using ${VARNAME} Closes jaagr/lemonbuddy#36 --- README.md | 3 ++ include/utils/config.hpp | 62 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8d77c830..275ed1bc 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,9 @@ The configuration syntax is based on the `ini` file format. ; Other values can be referenced using: key = ${section.key} + + ; Environment variables can be referenced using: + key = ${env:VAR_NAME} ~~~ ~~~ ini [section/name] diff --git a/include/utils/config.hpp b/include/utils/config.hpp index 800c3805..ef305987 100644 --- a/include/utils/config.hpp +++ b/include/utils/config.hpp @@ -2,6 +2,7 @@ #include +#include #include #include @@ -20,30 +21,71 @@ namespace config static std::recursive_mutex mtx; + /** + * Gets the path used to access the current bar section + */ std::string get_bar_path(); + + /** + * Sets the path used to access the current bar section + */ void set_bar_path(std::string path); + /** + * Loads a configuration file + */ void load(std::string path); + + /** + * Loads a configuration file + */ void load(const char *dir, std::string path); + + /** + * Reloads the configuration values + * TODO: Implement properly + */ // void reload(); + /** + * Gets the boost property tree handler + */ boost::property_tree::ptree get_tree(); + /** + * Builds the path used to find a parameter in the given section + */ std::string build_path(std::string section, std::string key); + /** + * Gets the location of the configuration file + */ std::string get_file_path(); + /** + * Finds the value of a config parameter defined + * as a reference variable using ${section.param} or ${env:VAR} + */ template T dereference_var(std::string ref_section, std::string ref_key, std::string var, const T ref_val) { std::lock_guard lck(config::mtx); - std::string::size_type n, m; + auto n = var.find("${"); + auto m = var.find("}"); - if ((n = var.find("${")) != 0) return ref_val; - if ((m = var.find("}")) != var.length()-1) return ref_val; + if (n != 0 || m != var.length()-1) + return ref_val; auto path = var.substr(2, m-2); + + if (path.find("env:") == 0) { + auto *envvar_value = std::getenv(path.substr(4).c_str()); + if (envvar_value != nullptr) + return boost::lexical_cast(envvar_value); + return ref_val; + } + auto ref_path = build_path(ref_section, ref_key); if ((n = path.find(".")) == std::string::npos) @@ -62,6 +104,9 @@ namespace config return dereference_var(section, key, str_val, val.get()); } + /** + * Gets the value of a variable by section and parameter name + */ template T get(std::string section, std::string key) { @@ -77,6 +122,10 @@ namespace config return dereference_var(section, key, str_val, val.get()); } + /** + * Gets the value of a variable by section and parameter name + * with a default value in case the parameter isn't defined + */ template T get(std::string section, std::string key, T default_value) { @@ -88,6 +137,9 @@ namespace config return dereference_var(section, key, str_val.get_value_or(""), val.get_value_or(default_value)); } + /** + * Gets a list of values by section and parameter name + */ template std::vector get_list(std::string section, std::string key) { @@ -107,6 +159,10 @@ namespace config return vec; } + /** + * Gets a list of values by section and parameter name + * with a default list in case the list isn't defined + */ template std::vector get_list(std::string section, std::string key, std::vector default_value) {