Skip to content
Snippets Groups Projects
Commit 3fb778d9 authored by Christian Engwer's avatar Christian Engwer
Browse files

[parametertree] add new command line parser, which support keywords

parent 837804da
No related branches found
No related tags found
No related merge requests found
......@@ -14,8 +14,8 @@
#include <sstream>
#include <fstream>
#include <set>
#include <dune/common/exceptions.hh>
#include <map>
#include <algorithm>
std::string Dune::ParameterTreeParser::ltrim(const std::string& s)
{
......@@ -132,7 +132,6 @@ void Dune::ParameterTreeParser::readINITree(std::istream& in,
}
void Dune::ParameterTreeParser::readOptions(int argc, char* argv [],
ParameterTree& pt)
{
......@@ -158,3 +157,92 @@ void Dune::ParameterTreeParser::readOptions(int argc, char* argv [],
}
}
void Dune::ParameterTreeParser::readNamedOptions(int argc, char* argv[],
ParameterTree& pt,
std::vector<std::string> keywords,
unsigned int required,
bool allow_more,
bool overwrite,
std::vector<std::string> help)
{
std::string helpstr = generateHelpString(argv[0], keywords, required, help);
std::vector<bool> done(keywords.size(),false);
std::size_t current = 0;
for (std::size_t i=1; i<std::size_t(argc); i++)
{
std::string opt = argv[i];
// check for help
if (opt == "-h" || opt == "--help")
DUNE_THROW(HelpRequest, helpstr);
// is this a named parameter?
if (opt.substr(0,2) == "--")
{
size_t pos = opt.find('=',2);
if (pos == std::string::npos)
DUNE_THROW(ParameterTreeParserError,
"value missing for parameter " << opt << "\n" << helpstr);
std::string key = opt.substr(2,pos-2);
std::string value = opt.substr(pos+1,opt.size()-pos-1);
auto it = std::find(keywords.begin(), keywords.end(), key);
// is this param in the keywords?
if (!allow_more && it == keywords.end())
DUNE_THROW(ParameterTreeParserError,
"unknown parameter " << key << "\n" << helpstr);
// do we overwrite an existing entry?
if (!overwrite && pt[key] != "")
DUNE_THROW(ParameterTreeParserError,
"parameter " << key << " already specified" << "\n" << helpstr);
pt[key] = value;
done[std::distance(keywords.begin(),it)] = true; // mark key as stored
}
else {
// map to the next keyword in the list
while(current < done.size() && done[current]) ++current;
// are there keywords left?
if (current >= done.size())
DUNE_THROW(ParameterTreeParserError,
"superfluous unnamed parameter" << "\n" << helpstr);
// do we overwrite an existing entry?
if (!overwrite && pt[keywords[current]] != "")
DUNE_THROW(ParameterTreeParserError,
"parameter " << keywords[current] << " already specified" << "\n" << helpstr);
pt[keywords[current]] = opt;
done[current] = true; // mark key as stored
}
}
// check that we receive all required keywords
std::string missing = "";
for (unsigned int i=0; i<keywords.size(); i++)
if ((i < required) && ! done[i]) // is this param required?
missing += std::string(" ") + keywords[i];
if (missing.size())
DUNE_THROW(ParameterTreeParserError,
"missing parameter(s) ... " << missing << "\n" << helpstr);
}
std::string Dune::ParameterTreeParser::generateHelpString(
std::string progname, std::vector<std::string> keywords, unsigned int required, std::vector<std::string> help)
{
static const char braces[] = "<>[]";
std::string helpstr = "";
helpstr = helpstr + "Usage: " + progname;
for (std::size_t i=0; i<keywords.size(); i++)
{
bool req = (i < required);
helpstr = helpstr +
" " + braces[req*2] +
keywords[i] +braces[req*2+1];
}
helpstr = helpstr + "\n"
"Options:\n"
"-h / --help: this help\n";
for (std::size_t i=0; i<std::min(keywords.size(),help.size()); i++)
{
if (help[i] != "")
helpstr = helpstr + "-" +
keywords[i] + ":\t" + help[i] + "\n";
}
return helpstr;
}
......@@ -9,11 +9,16 @@
#include <istream>
#include <string>
#include <vector>
#include <dune/common/parametertree.hh>
#include <dune/common/exceptions.hh>
namespace Dune {
class ParameterTreeParserError : public RangeError {};
class HelpRequest : public Exception {};
/** \brief Parsers to set up a ParameterTree from various input sources
* \ingroup Common
*
......@@ -75,7 +80,7 @@ namespace Dune {
* Parses C++ stream and build hierarchical config structure.
*
* \param in The stream to parse
* \param pt The parameter tree to store the config structure.
* \param[out] pt The parameter tree to store the config structure.
* \param overwrite Whether to overwrite already existing values.
* If false, values in the stream will be ignored
* if the key is already present.
......@@ -93,7 +98,7 @@ namespace Dune {
* Parses C++ stream and build hierarchical config structure.
*
* \param in The stream to parse
* \param pt The parameter tree to store the config structure.
* \param[out] pt The parameter tree to store the config structure.
* \param srcname Name of the configuration source for error
* messages, "stdin" or a filename.
* \param overwrite Whether to overwrite already existing values.
......@@ -110,7 +115,7 @@ namespace Dune {
* Parses file with given name and build hierarchical config structure.
*
* \param file filename
* \param pt The parameter tree to store the config structure.
* \param[out] pt The parameter tree to store the config structure.
* \param overwrite Whether to overwrite already existing values.
* If false, values in the stream will be ignored
* if the key is already present.
......@@ -128,10 +133,37 @@ namespace Dune {
*
* \param argc arg count
* \param argv arg values
* \param pt The parameter tree to store the config structure.
* \param[out] pt The parameter tree to store the config structure.
*/
static void readOptions(int argc, char* argv [], ParameterTree& pt);
/**
* \brief read [named] command line options and build hierarchical ParameterTree structure
*
* Similar to pythons named options we expect the parameters in the
* ordering induced by keywords, but allow the user to pass named options
* in the form of --key=value. Optionally the user can pass an additional
* vector with help strings.
*
* \param argc arg count
* \param argv arg values
* \param[out] pt The parameter tree to store the config structure.
* \param keywords vector with keywords names
* \param required number of required options (the first n keywords are required, default is all are required)
* \param allow_more allow more options than these listed in keywords (default = true)
* \param overwrite allow to overwrite existing options (default = true)
* \param help vector containing help strings
*/
static void readNamedOptions(int argc, char* argv[],
ParameterTree& pt,
std::vector<std::string> keywords,
unsigned int required = std::numeric_limits<unsigned int>::max(),
bool allow_more = true,
bool overwrite = true,
std::vector<std::string> help = std::vector<std::string>());
private:
static std::string generateHelpString(std::string progname, std::vector<std::string> keywords, unsigned int required, std::vector<std::string> help);
};
} // end namespace Dune
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment