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. 62
      src/utility/settings.cpp
  2. 27
      src/utility/settings.h

62
src/utility/settings.cpp

@ -7,7 +7,7 @@
#include "src/utility/settings.h"
//#include <iostream>
#include <iostream>
//#include <boost/program_options.hpp>
//#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);
}
/*
* 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,
@ -123,6 +144,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
*/
@ -178,5 +229,4 @@ Settings* instance()
}
} // namespace settings
} // namespace mrmc

27
src/utility/settings.h

@ -10,6 +10,7 @@
#include <iostream>
#include <list>
#include <utility>
#include <boost/program_options.hpp>
#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<fptr_regOption> reg_list;
std::list<std::pair<CallbackType, RegisterCallback>> registerList;
/*!
* @brief Stores check callbacks.
*/
std::list<fptr_checkOption> check_list;
std::list<CheckerCallback> 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<CallbackType, RegisterCallback>(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);
}
};

Loading…
Cancel
Save