Browse Source

Changed Settings class to be singleton

Changed a lot in the class structure of Settings:

* Settings is now a Singleton. Obtain a new instance by Settings::instance().
* options_description objects are now static, thus a help message can be printed even if the constructor of Settings failes
* As Settings has static members, a .cpp file became necessary, hence cmake should probably be run...
* Help messages can be printed with new help and helpConfigfile routines
tempestpy_adaptions
gereon 12 years ago
parent
commit
a5a045f091
  1. 9
      src/mrmc-cpp.cpp
  2. 179
      src/utility/settings.cpp
  3. 167
      src/utility/settings.h

9
src/mrmc-cpp.cpp

@ -42,22 +42,23 @@ int main(const int argc, const char* argv[]) {
try try
{ {
s = new mrmc::settings::Settings(argc, argv, NULL);
s = mrmc::settings::Settings::instance(argc, argv, NULL);
} }
catch (mrmc::exceptions::InvalidSettings) catch (mrmc::exceptions::InvalidSettings)
{ {
std::cout << "Could not recover from settings error, terminating." << std::endl;
std::cout << "Could not recover from settings error, terminating." << std::endl << std::endl;
std::cout << mrmc::settings::help << std::endl;
return 1; return 1;
} }
if (s->isSet("help")) if (s->isSet("help"))
{ {
std::cout << s->getHelpForCommandline() << std::endl;
std::cout << mrmc::settings::help << std::endl;
return 0; return 0;
} }
if (s->isSet("help-config")) if (s->isSet("help-config"))
{ {
std::cout << s->getHelpForConfigfile() << std::endl;
std::cout << mrmc::settings::helpConfigfile << std::endl;
return 0; return 0;
} }

179
src/utility/settings.cpp

@ -0,0 +1,179 @@
/*
* settings.cpp
*
* Created on: 22.11.2012
* Author: Gereon Kremer
*/
#include "src/utility/settings.h"
//#include <iostream>
//#include <boost/program_options.hpp>
//#include "src/exceptions/InvalidSettings.h"
namespace mrmc {
namespace settings {
namespace bpo = boost::program_options;
bpo::options_description mrmc::settings::Settings::configfile("Config Options");
bpo::options_description mrmc::settings::Settings::generic("Generic Options");
bpo::options_description mrmc::settings::Settings::commandline("Commandline Options");
bpo::positional_options_description mrmc::settings::Settings::positional;
bpo::options_description mrmc::settings::Settings::cli;
bpo::options_description mrmc::settings::Settings::conf;
mrmc::settings::Settings* mrmc::settings::Settings::inst = NULL;
/*!
* The constructor fills the option descriptions, parses the
* command line and the config file and puts the option values to
* our option mapping.
*
* If a configfile is set in the commandline, we load this one.
* Otherwise, if filename is not NULL, we load this one. Otherwise,
* we load no config file.
*
* @param argc should be argc passed to main function
* @param argv should be argv passed to main function
* @param filename either NULL or name of config file
*/
Settings::Settings(const int argc, const char* argv[], const char* filename)
{
try
{
/*
* load command line
*/
bpo::store(bpo::command_line_parser(argc, argv).options(this->cli).positional(this->positional).run(), this->vm);
/*
* load config file if specified
*/
if (this->vm.count("configfile"))
{
bpo::store(bpo::parse_config_file<char>(this->vm["configfile"].as<std::string>().c_str(), this->conf), this->vm, true);
}
else if (filename != NULL)
{
bpo::store(bpo::parse_config_file<char>(filename, this->conf), this->vm, true);
}
bpo::notify(this->vm);
}
/*
* catch errors...
*/
catch (bpo::reading_file e)
{
std::cout << "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;
throw mrmc::exceptions::InvalidSettings();
}
}
catch (bpo::error e)
{
std::cout << "Some error occurred: " << e.what() << std::endl;
}
}
/*!
* Creates a new instance if necessary. When the instance is actually
* created for the first time, the internal options_description objects are
* initialized.
*
* If this function was already called and another instance is
* already present, the existing instance will be returned. In this
* case, better use the routine mrmc::settings::instance().
*
* The constructor fills the option descriptions, parses the
* command line and the config file and puts the option values to
* our option mapping.
*
* If a configfile is set in the commandline, we load this one.
* Otherwise, if filename is not NULL, we load this one. Otherwise,
* we load no config file.
*
* @param argc should be argc passed to main function
* @param argv should be argv passed to main function
* @param filename either NULL or name of config file
* @return instance of Settings
*/
Settings* Settings::instance(const int argc, const char* argv[], const char* filename)
{
if (Settings::inst == NULL) {
/*
* fill option descriptions
*/
Settings::commandline.add_options()
("help", "produce help message")
("help-config", "produce help message about config file")
("configfile", bpo::value<std::string>(), "name of config file")
;
Settings::generic.add_options()
("trafile", bpo::value<std::string>()->required(), "name of the .tra file")
("labfile", bpo::value<std::string>()->required(), "name of the .lab file")
;
Settings::configfile.add_options()
;
/*
* construct option descriptions for commandline and config file
*/
Settings::cli.add(Settings::commandline).add(generic);
Settings::conf.add(Settings::configfile).add(generic);
/*
* Take care of positional arguments
*/
Settings::positional.add("trafile", 1);
Settings::positional.add("labfile", 1);
/*
* Actually create new instance
*/
Settings::inst = new Settings(argc, argv, filename);
}
return Settings::inst;
}
/*!
* Print a short general usage information consisting of the positional
* options and the list of available command line options.
*
* Use it like this:
* @code std::cout << mrmc::settings::help; @endcode
*/
std::ostream& help(std::ostream& os)
{
os << "Usage: <binary> [options] <transition file> <label file>" << std::endl;
os << Settings::cli << std::endl;;
return os;
}
/*!
* Print a list of available options for the config file.
*
* Use it like this:
* @code std::cout << mrmc::settings::helpConfigfile; @endcode
*/
std::ostream& helpConfigfile(std::ostream& os)
{
os << Settings::conf << std::endl;;
return os;
}
/*!
* @return current instance.
*/
Settings* instance()
{
return Settings::inst;
}
} // namespace settings
} // namespace mrmc

167
src/utility/settings.h

@ -13,155 +13,116 @@
#include "src/exceptions/InvalidSettings.h" #include "src/exceptions/InvalidSettings.h"
namespace mrmc { namespace mrmc {
namespace settings {
/*!
* The settings namespace contains the Settings class and all associated
* methods.
*/
namespace settings {
namespace bpo = boost::program_options; namespace bpo = boost::program_options;
/*! /*!
* @brief Simple wrapper around boost::program_options to handle configuration options. * @brief Simple wrapper around boost::program_options to handle configuration options.
* *
* This class uses boost::program_options to read options from the * This class uses boost::program_options to read options from the
* commandline and additionally load options from a file. * commandline and additionally load options from a file.
*
* It is meant to be used as a singleton. Call
* @code mrmc::settings::Settings::instance(argc, argv, filename) @endcode
* to initialize it and obtain an instance for the first time.
* Afterwards, it is possible to use
* @code mrmc::settings::instance() @endcode
*/ */
class Settings class Settings
{ {
public: public:
/*!
* @brief Constructor of Settings file
*
* The constructor fills the option descriptions, parses the
* command line and the config file and puts the option values to
* our option mapping.
*
* If a configfile is set in the commandline, we load this one.
* Otherwise, if filename is not NULL, we load this one. Otherwise,
* we load no config file.
*
* @param argc should be argc passed to main function
* @param argv should be argv passed to main function
* @param filename either NULL or name of config file
*/
Settings(const int argc, const char* argv[], const char* filename)
: configfile("Config Options"), generic("Generic Options"), commandline("Commandline Options")
{
/*
* fill option descriptions
*/
this->commandline.add_options()
("help", "produce help message")
("help-config", "produce help message about config file")
("configfile", bpo::value<std::string>(), "name of config file")
;
this->generic.add_options()
("trafile", bpo::value<std::string>()->required(), "name of the .tra file")
("labfile", bpo::value<std::string>()->required(), "name of the .lab file")
;
this->configfile.add_options()
;
this->positional.add("trafile", 1);
this->positional.add("labfile", 1);
/*
* construct option descriptions for commandline and config file
*/
this->cli.add(this->commandline).add(generic);
this->conf.add(this->configfile).add(generic);
try
{
/*
* load command line
*/
bpo::store(bpo::command_line_parser(argc, argv).options(this->cli).positional(this->positional).run(), this->vm);
/*
* load config file if specified
*/
if (this->vm.count("configfile"))
{
bpo::store(bpo::parse_config_file<char>(this->vm["configfile"].as<std::string>().c_str(), this->conf), this->vm, true);
}
else if (filename != NULL)
{
bpo::store(bpo::parse_config_file<char>(filename, this->conf), this->vm, true);
}
bpo::notify(this->vm);
}
/*
* catch errors...
*/
catch (bpo::reading_file e)
{
std::cout << "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;
throw mrmc::exceptions::InvalidSettings();
}
}
catch (bpo::error e)
{
std::cout << "Some error occurred: " << e.what() << std::endl;
}
}
/*! /*!
* @brief Get option descriptions for commandline options * @brief Get option descriptions for commandline options
*/ */
bpo::options_description& getHelpForCommandline()
{
bpo::options_description& getHelpForCommandline() const {
return this->cli; return this->cli;
} }
/*! /*!
* @brief Get option descriptions for config file options * @brief Get option descriptions for config file options
*/ */
bpo::options_description& getHelpForConfigfile()
{
bpo::options_description& getHelpForConfigfile() const {
return this->conf; return this->conf;
} }
/*! /*!
* @brief Get value of string argument
* @brief Get value of string option
*/ */
const std::string& getString(const std::string &name) const
{
const std::string& getString(const std::string &name) const {
return this->vm[name].as<std::string>(); return this->vm[name].as<std::string>();
} }
const bool isSet(const std::string &name) const
{
/*!
* @brief Check if an option is set
*/
const bool isSet(const std::string &name) const {
return this->vm.count(name) > 0; return this->vm.count(name) > 0;
} }
friend std::ostream& help(std::ostream& os);
friend std::ostream& helpConfigfile(std::ostream& os);
friend Settings* instance();
/*!
* @brief Creates a new instance.
*/
static Settings* instance(const int argc, const char* argv[], const char* filename);
private: private:
/*! /*!
* @brief option descriptions
* @brief Constructor.
*/
Settings(const int argc, const char* argv[], const char* filename);
/*!
* @brief Option descriptions.
*/ */
bpo::options_description configfile;
bpo::options_description generic;
bpo::options_description commandline;
bpo::positional_options_description positional;
static bpo::options_description configfile;
static bpo::options_description generic;
static bpo::options_description commandline;
static bpo::positional_options_description positional;
/*! /*!
* @brief collecing option descriptions
* @brief Collecting option descriptions.
* *
* The options for command line and config file are collected * The options for command line and config file are collected
* here
* here.
*/ */
bpo::options_description cli;
bpo::options_description conf;
static bpo::options_description cli;
static bpo::options_description conf;
/*! /*!
* @brief option mapping
* @brief option mapping.
*/ */
bpo::variables_map vm; bpo::variables_map vm;
/*!
* @brief actual instance of this class.
*/
static Settings* inst;
}; };
/*!
* @brief Print usage help.
*/
std::ostream& help(std::ostream& os);
/*!
* @brief Print help for config file options.
*/
std::ostream& helpConfigfile(std::ostream& os);
/*!
* @brief Return current instance.
*/
Settings* instance();
} // namespace parser } // namespace parser
} // namespace mrmc } // namespace mrmc
Loading…
Cancel
Save