diff --git a/src/utility/settings.cpp b/src/utility/settings.cpp index 037243de4..a268ec684 100644 --- a/src/utility/settings.cpp +++ b/src/utility/settings.cpp @@ -7,7 +7,7 @@ #include "src/utility/settings.h" -//#include +#include //#include //#include "src/exceptions/InvalidSettings.h" @@ -58,26 +58,46 @@ Settings::Settings(const int argc, const char* argv[], const char* filename) { bpo::store(bpo::parse_config_file(filename, this->conf), this->vm, true); } + /* + * If a required option is missing, this will throw a bpo::required_option. + * This exception is catched below. + */ bpo::notify(this->vm); + + /* + * Call custom option checker. + */ + Callbacks* cb = mrmc::settings::Callbacks::getInstance(); + while (cb->checkerList.size() > 0) + { + CheckerCallback fptr = cb->checkerList.front(); + cb->checkerList.pop_front(); + + if (! (*fptr)(this->vm)) + { + std::cerr << "Custom option checker failed." << std::endl; + throw mrmc::exceptions::InvalidSettings(); + } + } } /* * catch errors... */ catch (bpo::reading_file e) { - std::cout << "Could not read config file " << filename << std::endl; + std::cerr << "Could not read config file " << filename << std::endl; } catch (bpo::required_option e) { if (! (this->vm.count("help") || this->vm.count("help-config"))) { - std::cout << e.what() << std::endl; + std::cerr << e.what() << std::endl; throw mrmc::exceptions::InvalidSettings(); } } catch (bpo::error e) { - std::cout << "Some error occurred: " << e.what() << std::endl; + std::cerr << "Some error occurred: " << e.what() << std::endl; } } @@ -92,7 +112,8 @@ Settings::Settings(const int argc, const char* argv[], const char* filename) * * The constructor fills the option descriptions, parses the * command line and the config file and puts the option values to - * our option mapping. + * our option mapping. It also calls all register callbacks that were + * registered via Callbacks and Register classes. * * If a configfile is set in the commandline, we load this one. * Otherwise, if filename is not NULL, we load this one. Otherwise, @@ -122,6 +143,36 @@ Settings* Settings::instance(const int argc, const char* argv[], const char* fil ; Settings::configfile.add_options() ; + + /* + * Call all custom register callbacks. + */ + Callbacks* cb = mrmc::settings::Callbacks::getInstance(); + while (cb->registerList.size() > 0) + { + CallbackType type = cb->registerList.front().first; + RegisterCallback fptr = cb->registerList.front().second; + cb->registerList.pop_front(); + + /* + * Allow modules to specify the type of an option. + */ + switch (type) + { + case CB_CONFIG: + (*fptr)(Settings::configfile); + break; + case CB_CLI: + (*fptr)(Settings::commandline); + break; + case CB_GENERIC: + (*fptr)(Settings::generic); + break; + default: + // hm. is this an error? can this actually happen with an enum? + break; + } + } /* * construct option descriptions for commandline and config file @@ -176,7 +227,6 @@ Settings* instance() { return Settings::inst; } - -} // namespace settings +} // namespace settings } // namespace mrmc diff --git a/src/utility/settings.h b/src/utility/settings.h index abcc139af..10fba3520 100644 --- a/src/utility/settings.h +++ b/src/utility/settings.h @@ -10,6 +10,7 @@ #include #include +#include #include #include "src/exceptions/InvalidSettings.h" @@ -123,13 +124,14 @@ namespace settings { /*! * @brief Function type for functions registering new options. */ - typedef void(*fptr_regOption)(bpo::options_description&); + typedef void(*RegisterCallback)(bpo::options_description&); /*! * @brief Function type for function checking constraints on settings. */ - typedef bool(*fptr_checkOption)(bpo::variables_map&); + typedef bool(*CheckerCallback)(bpo::variables_map&); + enum CallbackType { CB_CONFIG, CB_CLI, CB_GENERIC }; /*! * @brief This class handles callbacks for registering new options and @@ -144,11 +146,11 @@ namespace settings { /*! * @brief Stores register callbacks. */ - std::list reg_list; + std::list> registerList; /*! * @brief Stores check callbacks. */ - std::list check_list; + std::list checkerList; /*! * @brief Private constructor. @@ -167,16 +169,21 @@ namespace settings { * @brief Returns current instance to create singleton. * @return current instance */ - static Callbacks& getInstance() + static Callbacks* getInstance() { static Callbacks instance; - return instance; + return &instance; } /*! * @brief Register class needs access to lists. */ friend class Register; + + /*! + * @brief Settings class need access to lists. + */ + friend class Settings; }; /*! @@ -189,17 +196,17 @@ namespace settings { /*! * @brief Registers given function as register callback. */ - Register(const fptr_regOption ptr) + Register(const CallbackType type, const RegisterCallback ptr) { - mrmc::settings::Callbacks::getInstance().reg_list.push_back(ptr); + mrmc::settings::Callbacks::getInstance()->registerList.push_back(std::pair(type, ptr)); } /*! * @brief Registers given function as check callback. */ - Register(const fptr_checkOption ptr) + Register(const CheckerCallback ptr) { - mrmc::settings::Callbacks::getInstance().check_list.push_back(ptr); + mrmc::settings::Callbacks::getInstance()->checkerList.push_back(ptr); } };