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)
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)
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;
179 unsigned longest = 0;
180 for (
const std::pair<std::string, OptionBase *> nopt :
getOptionsMap())
191 if (
name.length() > longest) longest =
name.length();
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())
217 if (handled.find(option) != handled.end())
continue;
218 handled.insert(option);
231 ss <<
" -" << possibility <<
std::string(longest - possibility.length() + 2,
' ');
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;
324 template <
typename T>
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;
408 template <
typename T>
418 assert(!
name.empty() &&
"OptionMap: empty option name given");
431 if (s == std::get<1>(op))
434 value = std::get<0>(op);
456 template <
typename T>
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 std::vector< std::string > parseOptions(int argc, char *argv[], std::string description, std::string callFormat)
static std::string buildUsage(const std::string description, const std::string argv0, const std::string callFormat)
std::tuple< T, std::string, std::string > OptionPossibility
PossibilityDescriptions possibilityDescriptions
For when we have possibilities like in an OptionMap.
static OptionBase * getOption(const std::string optName)
Find option based on name in options map. Returns nullptr if not found.
static std::map< std::string, OptionBase * > & getOptionsMap(void)
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)
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
unsigned long int strtoul(const char *str, char **endptr, int base)