9#include <unordered_map>
10#include <unordered_set>
41 assert(
name[0] !=
'-' &&
"OptionBase: name starts with '-'");
79 std::vector<std::string> positionalArguments;
81 for (
int i = 1; i < argc; ++i)
83 std::string arg(argv[i]);
84 if (arg.empty())
continue;
89 positionalArguments.push_back(arg);
100 size_t equalsSign = arg.find(
'=');
101 if (equalsSign != std::string::npos)
104 argName = arg.substr(0, equalsSign);
110 std::cerr <<
"Unknown option: " << argName << std::endl;
114 argValue = arg.substr(equalsSign + 1);
124 std::cerr <<
"Unknown option: " << argName << std::endl;
140 else if (i + 1 < argc)
144 argValue = std::string(argv[i]);
148 std::cerr <<
"Expected value for: " << argName << std::endl;
155 std::cerr <<
"Unable to set: " << argName <<
"; check for duplicates" << std::endl;
162 std::cerr <<
"Bad value for: " << argName << std::endl;
167 return positionalArguments;
175 const std::string
description,
const std::string argv0,
const std::string callFormat
179 unsigned longest = 0;
180 for (
const std::pair<std::string, OptionBase *> nopt :
getOptionsMap())
182 const std::string
name = std::get<0>(nopt);
191 if (
name.length() > longest) longest =
name.length();
196 const std::string possibility = std::get<0>(pd);
197 if (possibility.length() + 3 > longest) longest = possibility.length() + 3;
201 std::stringstream ss;
205 ss <<
"USAGE:" << std::endl;
206 ss <<
" " << argv0 <<
" " << callFormat << std::endl;
209 ss <<
"OPTIONS:" << std::endl;
212 std::unordered_set<const OptionBase *> handled;
213 for (
const std::pair<std::string, OptionBase *> nopt :
getOptionsMap())
215 const std::string
name = std::get<0>(nopt);
217 if (handled.find(option) != handled.end())
continue;
218 handled.insert(option);
229 const std::string possibility = std::get<0>(pd);
231 ss <<
" -" << possibility << std::string(longest - possibility.length() + 2,
' ');
243 ss <<
" -" <<
name << std::string(longest -
name.length() + 2,
' ');
247 const std::string possibility = std::get<0>(pd);
249 ss <<
" =" << possibility << std::string(longest - possibility.length() + 2,
' ');
257 ss <<
" -help" << std::string(longest - 4 + 2,
' ') <<
"- show usage and exit" << std::endl;
258 ss <<
" -h" << std::string(longest - 1 + 2,
' ') <<
"- show usage and exit" << std::endl;
262 ss <<
"Note: for boolean options, -name true and -name false are invalid." << std::endl;
263 ss <<
" Use -name, -name=true, or -name=false." << std::endl;
273 else return optIt->second;
279 if (
error) std::cerr << usage;
280 else std::cout << usage;
281 std::exit(
error ? 1 : 0);
287 static std::vector<std::string> helpNames = {
"help",
"h",
"-help"};
288 return std::find(helpNames.begin(), helpNames.end(),
name) != helpNames.end();
310 static std::map<std::string, OptionBase *> options;
331 assert(!
name.empty() &&
"Option: empty option name given");
348 return std::is_same<T, bool>::value;
367 else if (s ==
"false")
385 if (s.empty())
return false;
388 if (!(c >=
'0' && c <=
'9'))
return false;
392 assert(
sizeof(
unsigned long) >=
sizeof(
u32_t));
393 const unsigned long sv = std::strtoul(s.c_str(),
nullptr, 10);
396 if (errno == ERANGE || sv > std::numeric_limits<u32_t>::max())
return false;
418 assert(!
name.empty() &&
"OptionMap: empty option name given");
431 if (s == std::get<1>(op))
434 value = std::get<0>(op);
472 std::string possibilityName = std::get<1>(op);
487 if (s == std::get<1>(op))
507 if (tb.second)
return false;
516 typename std::unordered_map<T, bool>::const_iterator ovIt =
optionValues.find(v);
std::pair< std::string, std::string > PossibilityDescription
Name/description pairs.
static PossibilityDescriptions extractPossibilityDescriptions(const std::vector< OptionPossibility< T > > possibilities)
OptionBase(std::string name, std::string description, PossibilityDescriptions possibilityDescriptions)
virtual bool canSet(void) const =0
Can this option be set?
static OptionBase * getOption(const std::string optName)
Find option based on name in options map. Returns nullptr if not found.
static std::string buildUsage(const std::string description, const std::string argv0, const std::string callFormat)
std::tuple< T, std::string, std::string > OptionPossibility
static std::vector< std::string > parseOptions(int argc, char *argv[], std::string description, std::string callFormat)
PossibilityDescriptions possibilityDescriptions
For when we have possibilities like in an OptionMap.
static void usageAndExit(const std::string usage, bool error)
Print usage and exit. If error is set, print to stderr and exits with code 1.
virtual bool isBool(void) const
virtual bool isMultiple(void) const
Whether this option is an OptionMultiple.
std::vector< std::pair< std::string, std::string > > PossibilityDescriptions
static bool isHelpName(const std::string name)
Returns whether name is one of the reserved help options.
OptionBase(std::string name, std::string description)
static std::map< std::string, OptionBase * > & getOptionsMap(void)
virtual bool parseAndSetValue(const std::string value)=0
From a given string, set the value of this option.
OptionPossibilities possibilities
std::vector< OptionPossibility< T > > OptionPossibilities
virtual bool parseAndSetValue(const std::string s) override
From a given string, set the value of this option.
virtual bool canSet(void) const override
Can this option be set?
OptionMap(std::string name, std::string description, T init, OptionPossibilities possibilities)
OptionMultiple(std::string description, OptionPossibilities possibilities)
std::unordered_map< T, bool > optionValues
bool nothingSet(void) const
If the bitset is empty.
std::vector< OptionPossibility< T > > OptionPossibilities
virtual bool canSet(void) const override
Can this option be set?
virtual bool isMultiple(void) const override
Whether this option is an OptionMultiple.
OptionPossibilities possibilities
virtual bool parseAndSetValue(const std::string s) override
From a given string, set the value of this option.
bool operator()(const T v) const
Returns whether the value v had been set as an option.
static bool fromString(const std::string &s, bool &value)
virtual bool canSet(void) const override
Can this option be set?
static bool fromString(const std::string s, u32_t &value)
virtual bool parseAndSetValue(const std::string s) override
From a given string, set the value of this option.
Option(const std::string &name, const std::string &description, T init)
static bool fromString(const std::string s, std::string &value)
virtual bool isBool(void) const override