Browse Source

made settings callbacks work and changed names to match our conventions.

it is possible to register callbacks that add custom options to the settings module.
it is also possible to register callbacks that perform checks on the variable assignment afterwards.

The registering is done during the static initialization phase, i.e. before main() does anything.
tempestpy_adaptions
gereon 12 years ago
parent
commit
4361647ef4
  1. 64
      src/utility/settings.cpp
  2. 27
      src/utility/settings.h

64
src/utility/settings.cpp

@ -7,7 +7,7 @@
#include "src/utility/settings.h" #include "src/utility/settings.h"
//#include <iostream>
#include <iostream>
//#include <boost/program_options.hpp> //#include <boost/program_options.hpp>
//#include "src/exceptions/InvalidSettings.h" //#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<char>(filename, this->conf), this->vm, true); bpo::store(bpo::parse_config_file<char>(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); 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 errors...
*/ */
catch (bpo::reading_file e) 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) catch (bpo::required_option e)
{ {
if (! (this->vm.count("help") || this->vm.count("help-config"))) 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(); throw mrmc::exceptions::InvalidSettings();
} }
} }
catch (bpo::error e) 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 * The constructor fills the option descriptions, parses the
* command line and the config file and puts the option values to * 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. * If a configfile is set in the commandline, we load this one.
* Otherwise, if filename is not NULL, we load this one. Otherwise, * 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() 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 * construct option descriptions for commandline and config file
@ -176,7 +227,6 @@ Settings* instance()
{ {
return Settings::inst; return Settings::inst;
} }
} // namespace settings
} // namespace settings
} // namespace mrmc } // namespace mrmc

27
src/utility/settings.h

@ -10,6 +10,7 @@
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <utility>
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include "src/exceptions/InvalidSettings.h" #include "src/exceptions/InvalidSettings.h"
@ -123,13 +124,14 @@ namespace settings {
/*! /*!
* @brief Function type for functions registering new options. * @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. * @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 * @brief This class handles callbacks for registering new options and
@ -144,11 +146,11 @@ namespace settings {
/*! /*!
* @brief Stores register callbacks. * @brief Stores register callbacks.
*/ */
std::list<fptr_regOption> reg_list;
std::list<std::pair<CallbackType, RegisterCallback>> registerList;
/*! /*!
* @brief Stores check callbacks. * @brief Stores check callbacks.
*/ */
std::list<fptr_checkOption> check_list;
std::list<CheckerCallback> checkerList;
/*! /*!
* @brief Private constructor. * @brief Private constructor.
@ -167,16 +169,21 @@ namespace settings {
* @brief Returns current instance to create singleton. * @brief Returns current instance to create singleton.
* @return current instance * @return current instance
*/ */
static Callbacks& getInstance()
static Callbacks* getInstance()
{ {
static Callbacks instance; static Callbacks instance;
return instance;
return &instance;
} }
/*! /*!
* @brief Register class needs access to lists. * @brief Register class needs access to lists.
*/ */
friend class Register; 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. * @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<CallbackType, RegisterCallback>(type, ptr));
} }
/*! /*!
* @brief Registers given function as check callback. * @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);
} }
}; };

Loading…
Cancel
Save