fix argh.h - use the one from mesytec-mvlc (same include guard)
This commit is contained in:
parent
f126ca307c
commit
cad7b29796
1 changed files with 489 additions and 300 deletions
|
@ -1,300 +1,489 @@
|
||||||
// Source: https://github.com/aardvarkk/argh
|
#ifndef BD0985AD_491A_464A_94D1_30155FF018C1
|
||||||
// The MIT License (MIT)
|
#define BD0985AD_491A_464A_94D1_30155FF018C1
|
||||||
//
|
|
||||||
// Copyright (c) 2014 Ian Clarkson
|
#include <algorithm>
|
||||||
//
|
#include <cassert>
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
#include <limits>
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
#include <map>
|
||||||
// in the Software without restriction, including without limitation the rights
|
#include <set>
|
||||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
#include <sstream>
|
||||||
// copies of the Software, and to permit persons to whom the Software is
|
#include <string>
|
||||||
// furnished to do so, subject to the following conditions:
|
#include <vector>
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included in all
|
namespace argh
|
||||||
// copies or substantial portions of the Software.
|
{
|
||||||
//
|
// Terminology:
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
// A command line is composed of 2 types of args:
|
||||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
// 1. Positional args, i.e. free standing values
|
||||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
// 2. Options: args beginning with '-'. We identify two kinds:
|
||||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
// 2.1: Flags: boolean options => (exist ? true : false)
|
||||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
// 2.2: Parameters: a name followed by a non-option value
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
// SOFTWARE.
|
#if !defined(__GNUC__) || (__GNUC__ >= 5)
|
||||||
#pragma once
|
using string_stream = std::istringstream;
|
||||||
|
#else
|
||||||
#include <algorithm>
|
// Until GCC 5, istringstream did not have a move constructor.
|
||||||
#include <fstream>
|
// stringstream_proxy is used instead, as a workaround.
|
||||||
#include <iomanip>
|
class stringstream_proxy
|
||||||
#include <sstream>
|
{
|
||||||
#include <string>
|
public:
|
||||||
#include <vector>
|
stringstream_proxy() = default;
|
||||||
|
|
||||||
class Option {
|
// Construct with a value.
|
||||||
public:
|
stringstream_proxy(std::string const &value)
|
||||||
Option() : parsed(false), required(false) {}
|
: stream_(value)
|
||||||
virtual ~Option() {};
|
{
|
||||||
|
}
|
||||||
virtual std::string getDefault() = 0;
|
|
||||||
virtual std::string getMessage() = 0;
|
// Copy constructor.
|
||||||
virtual std::string getName() = 0;
|
stringstream_proxy(const stringstream_proxy &other)
|
||||||
virtual void setValue(std::string const& val) = 0;
|
: stream_(other.stream_.str())
|
||||||
|
{
|
||||||
bool getParsed() { return parsed; }
|
stream_.setstate(other.stream_.rdstate());
|
||||||
bool getRequired() { return required; }
|
}
|
||||||
|
|
||||||
virtual void setParsed(bool parsed) { this->parsed = parsed; }
|
void setstate(std::ios_base::iostate state) { stream_.setstate(state); }
|
||||||
|
|
||||||
protected:
|
// Stream out the value of the parameter.
|
||||||
bool parsed, required;
|
// If the conversion was not possible, the stream will enter the fail state,
|
||||||
};
|
// and operator bool will return false.
|
||||||
|
template <typename T> stringstream_proxy &operator>>(T &thing)
|
||||||
template<typename T>
|
{
|
||||||
class OptionImpl : public Option {
|
stream_ >> thing;
|
||||||
public:
|
return *this;
|
||||||
OptionImpl(T& var, T default_val, std::string const& name, bool required, std::string const& msg) : var(var)
|
}
|
||||||
{
|
|
||||||
this->default_val = default_val;
|
// Get the string value.
|
||||||
this->name = name;
|
std::string str() const { return stream_.str(); }
|
||||||
this->required = required;
|
|
||||||
this->msg = msg;
|
std::stringbuf *rdbuf() const { return stream_.rdbuf(); }
|
||||||
this->var = default_val;
|
|
||||||
}
|
// Check the state of the stream.
|
||||||
|
// False when the most recent stream operation failed
|
||||||
virtual std::string getDefault() { std::stringstream ss; ss << default_val; return ss.str(); }
|
explicit operator bool() const { return !!stream_; }
|
||||||
std::string getName() { return name; }
|
|
||||||
std::string getMessage() { return msg; }
|
~stringstream_proxy() = default;
|
||||||
virtual void setValue(std::string const& val) { std::stringstream ss(val); ss >> var; }
|
|
||||||
|
private:
|
||||||
protected:
|
std::istringstream stream_;
|
||||||
T default_val;
|
};
|
||||||
T& var;
|
using string_stream = stringstream_proxy;
|
||||||
std::string name;
|
#endif
|
||||||
std::string msg;
|
|
||||||
};
|
class multimap_iteration_wrapper
|
||||||
|
{
|
||||||
class OptionStringImpl : public OptionImpl<std::string>
|
public:
|
||||||
{
|
using container_t = std::multimap<std::string, std::string>;
|
||||||
public:
|
using iterator_t = container_t::const_iterator;
|
||||||
OptionStringImpl(std::string& var, std::string const& default_val, std::string const& name, bool required, std::string const& msg) :
|
using difference_t = container_t::difference_type;
|
||||||
OptionImpl(var, default_val, name, required, msg)
|
explicit multimap_iteration_wrapper(const iterator_t &lb, const iterator_t &ub)
|
||||||
{}
|
: lb_(lb)
|
||||||
|
, ub_(ub)
|
||||||
std::string getDefault() { std::stringstream ss; ss << "\"" << default_val << "\""; return ss.str(); }
|
{
|
||||||
void setValue(std::string const& val) { var = val; }
|
}
|
||||||
};
|
|
||||||
|
iterator_t begin() const { return lb_; }
|
||||||
template<typename T>
|
iterator_t end() const { return ub_; }
|
||||||
class MultiOptionImpl : public Option
|
difference_t size() const { return std::distance(lb_, ub_); }
|
||||||
{
|
|
||||||
public:
|
private:
|
||||||
MultiOptionImpl(std::vector<T>& var, std::string const& default_vals, std::string const& name, bool required, std::string const& msg, char delim) : var(var)
|
iterator_t lb_;
|
||||||
{
|
iterator_t ub_;
|
||||||
this->default_vals = default_vals;
|
};
|
||||||
this->name = name;
|
|
||||||
this->required = required;
|
class parser
|
||||||
this->msg = msg;
|
{
|
||||||
this->delim = delim;
|
public:
|
||||||
setValue(default_vals);
|
enum Mode
|
||||||
}
|
{
|
||||||
|
PREFER_FLAG_FOR_UNREG_OPTION = 1 << 0,
|
||||||
std::string getDefault()
|
PREFER_PARAM_FOR_UNREG_OPTION = 1 << 1,
|
||||||
{
|
NO_SPLIT_ON_EQUALSIGN = 1 << 2,
|
||||||
std::stringstream ss;
|
SINGLE_DASH_IS_MULTIFLAG = 1 << 3,
|
||||||
ss << "\"";
|
};
|
||||||
ss << default_vals;
|
|
||||||
ss << "\"";
|
parser() = default;
|
||||||
return ss.str();
|
|
||||||
}
|
parser(std::initializer_list<char const *const> pre_reg_names) { add_params(pre_reg_names); }
|
||||||
|
|
||||||
std::string getName() { return name; }
|
parser(const char *const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION) { parse(argv, mode); }
|
||||||
std::string getMessage() { return msg; }
|
|
||||||
virtual void setValue(std::string const& val) {
|
parser(int argc, const char *const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION)
|
||||||
var.clear();
|
{
|
||||||
std::stringstream ss(val);
|
parse(argc, argv, mode);
|
||||||
T elem;
|
}
|
||||||
for (std::string val_str; std::getline(ss, val_str, delim);) {
|
|
||||||
std::stringstream st(val_str);
|
void add_param(std::string const &name);
|
||||||
st >> elem;
|
void add_params(std::string const &name);
|
||||||
var.push_back(elem);
|
|
||||||
}
|
void add_param(std::initializer_list<char const *const> init_list);
|
||||||
}
|
void add_params(std::initializer_list<char const *const> init_list);
|
||||||
|
|
||||||
protected:
|
void parse(const char *const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION);
|
||||||
std::string default_vals;
|
void parse(int argc, const char *const argv[], int mode = PREFER_FLAG_FOR_UNREG_OPTION);
|
||||||
std::vector<T>& var;
|
|
||||||
std::string name;
|
std::multiset<std::string> const &flags() const { return flags_; }
|
||||||
std::string msg;
|
std::multimap<std::string, std::string> const ¶ms() const { return params_; }
|
||||||
char delim;
|
multimap_iteration_wrapper params(std::string const &name) const;
|
||||||
};
|
std::vector<std::string> const &pos_args() const { return pos_args_; }
|
||||||
|
|
||||||
class MultiOptionStringImpl : public MultiOptionImpl<std::string>
|
// begin() and end() for using range-for over positional args.
|
||||||
{
|
std::vector<std::string>::const_iterator begin() const { return pos_args_.cbegin(); }
|
||||||
public:
|
std::vector<std::string>::const_iterator end() const { return pos_args_.cend(); }
|
||||||
MultiOptionStringImpl(std::vector<std::string>& var, std::string const& default_vals, std::string const& name, bool required, std::string const& msg, char delim) :
|
size_t size() const { return pos_args_.size(); }
|
||||||
MultiOptionImpl(var, default_vals, name, required, msg, delim)
|
|
||||||
{}
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Accessors
|
||||||
void setValue(std::string const& val) {
|
|
||||||
var.clear();
|
// flag (boolean) accessors: return true if the flag appeared, otherwise false.
|
||||||
std::stringstream ss(val);
|
bool operator[](std::string const &name) const;
|
||||||
for (std::string val_str; std::getline(ss, val_str, delim);) {
|
|
||||||
var.push_back(val_str);
|
// multiple flag (boolean) accessors: return true if at least one of the flag appeared,
|
||||||
}
|
// otherwise false.
|
||||||
}
|
bool operator[](std::initializer_list<char const *const> init_list) const;
|
||||||
};
|
|
||||||
|
// returns positional arg string by order. Like argv[] but without the options
|
||||||
class FlagImpl : public Option {
|
std::string const &operator[](size_t ind) const;
|
||||||
public:
|
|
||||||
FlagImpl(bool& flag, std::string const& name, std::string const& msg) :
|
// returns a std::istream that can be used to convert a positional arg to a typed value.
|
||||||
flag(flag),
|
string_stream operator()(size_t ind) const;
|
||||||
name(name),
|
|
||||||
msg(msg)
|
// same as above, but with a default value in case the arg is missing (index out of range).
|
||||||
{
|
template <typename T> string_stream operator()(size_t ind, T &&def_val) const;
|
||||||
flag = false;
|
|
||||||
}
|
// parameter accessors, give a name get an std::istream that can be used to convert to a typed
|
||||||
|
// value. call .str() on result to get as string
|
||||||
std::string getDefault() { return ""; }
|
string_stream operator()(std::string const &name) const;
|
||||||
std::string getName() { return name; }
|
|
||||||
std::string getMessage() { return msg; }
|
// accessor for a parameter with multiple names, give a list of names, get an std::istream that
|
||||||
void setParsed(bool parsed) { Option::setParsed(parsed); flag = parsed; }
|
// can be used to convert to a typed value. call .str() on result to get as string returns the
|
||||||
void setValue(std::string const&) {}
|
// first value in the list to be found.
|
||||||
|
string_stream operator()(std::initializer_list<char const *const> init_list) const;
|
||||||
protected:
|
|
||||||
bool& flag;
|
// same as above, but with a default value in case the param was missing.
|
||||||
std::string name;
|
// Non-string def_val types must have an operator<<() (output stream operator)
|
||||||
std::string msg;
|
// If T only has an input stream operator, pass the string version of the type as in "3" instead
|
||||||
};
|
// of 3.
|
||||||
|
template <typename T> string_stream operator()(std::string const &name, T &&def_val) const;
|
||||||
class Argh {
|
|
||||||
public:
|
// same as above but for a list of names. returns the first value to be found.
|
||||||
Argh(char delim = ',') : delim(delim) {}
|
template <typename T>
|
||||||
~Argh() { for (auto o : options) { delete o; } options.clear(); }
|
string_stream operator()(std::initializer_list<char const *const> init_list, T &&def_val) const;
|
||||||
|
|
||||||
void parse(int argc, char const* argv[]) {
|
private:
|
||||||
for (int i = 0; i < argc; ++i) {
|
string_stream bad_stream() const;
|
||||||
for (auto o : options) {
|
std::string trim_leading_dashes(std::string const &name) const;
|
||||||
if (std::string(argv[i]) == o->getName()) {
|
bool is_number(std::string const &arg) const;
|
||||||
o->setParsed(true);
|
bool is_option(std::string const &arg) const;
|
||||||
if (i + 1 < argc) {
|
bool got_flag(std::string const &name) const;
|
||||||
o->setValue(argv[i + 1]);
|
bool is_param(std::string const &name) const;
|
||||||
}
|
|
||||||
}
|
private:
|
||||||
}
|
std::vector<std::string> args_;
|
||||||
}
|
std::multimap<std::string, std::string> params_;
|
||||||
}
|
std::vector<std::string> pos_args_;
|
||||||
|
std::multiset<std::string> flags_;
|
||||||
void parseEnv() {
|
std::set<std::string> registeredParams_;
|
||||||
for (auto o : options) {
|
std::string empty_;
|
||||||
auto str = getenv(o->getName().c_str());
|
};
|
||||||
if (str) {
|
|
||||||
o->setParsed(true);
|
//////////////////////////////////////////////////////////////////////////
|
||||||
o->setValue(str);
|
|
||||||
}
|
inline void parser::parse(const char *const argv[], int mode)
|
||||||
}
|
{
|
||||||
}
|
int argc = 0;
|
||||||
|
for (auto argvp = argv; *argvp; ++argc, ++argvp)
|
||||||
template<typename T>
|
;
|
||||||
void addOption(T& var, T const& default_val, std::string const& name, bool required = false, std::string const& msg = "") {
|
parse(argc, argv, mode);
|
||||||
options.push_back(new OptionImpl<T>(var, default_val, name, required, msg));
|
}
|
||||||
}
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
void addOption(std::string& var, std::string const& default_val, std::string const& name, bool required = false, std::string const& msg = "") {
|
|
||||||
options.push_back(new OptionStringImpl(var, default_val, name, required, msg));
|
inline void parser::parse(int argc, const char *const argv[],
|
||||||
}
|
int mode /*= PREFER_FLAG_FOR_UNREG_OPTION*/)
|
||||||
|
{
|
||||||
template<typename T>
|
// clear out possible previous parsing remnants
|
||||||
void addMultiOption(std::vector<T>& var, std::string const& default_vals, std::string const& name, bool required = false, std::string const& msg = "") {
|
flags_.clear();
|
||||||
options.push_back(new MultiOptionImpl<T>(var, default_vals, name, required, msg, delim));
|
params_.clear();
|
||||||
}
|
pos_args_.clear();
|
||||||
|
|
||||||
void addMultiOption(std::vector<std::string>& var, std::string const& default_vals, std::string const& name, bool required = false, std::string const& msg = "") {
|
// convert to strings
|
||||||
options.push_back(new MultiOptionStringImpl(var, default_vals, name, required, msg, delim));
|
args_.resize(static_cast<decltype(args_)::size_type>(argc));
|
||||||
}
|
std::transform(argv, argv + argc, args_.begin(), [](const char *const arg) { return arg; });
|
||||||
|
|
||||||
void addFlag(bool& flag, std::string const& name, std::string const& msg = "") {
|
// parse line
|
||||||
options.push_back(new FlagImpl(flag, name, msg));
|
for (auto i = 0u; i < args_.size(); ++i)
|
||||||
}
|
{
|
||||||
|
if (!is_option(args_[i]))
|
||||||
std::string getUsage() {
|
{
|
||||||
size_t name_space = getLongestName() + 1;
|
pos_args_.emplace_back(args_[i]);
|
||||||
size_t default_space = getLongestDefault() + 1;
|
continue;
|
||||||
size_t msg_space = getLongestMessage() + 1;
|
}
|
||||||
|
|
||||||
std::stringstream ret;
|
auto name = trim_leading_dashes(args_[i]);
|
||||||
ret << std::left;
|
|
||||||
for (auto o : options) {
|
if (!(mode & NO_SPLIT_ON_EQUALSIGN))
|
||||||
ret
|
{
|
||||||
<< std::setw(static_cast<int>(name_space)) << o->getName()
|
auto equalPos = name.find('=');
|
||||||
<< std::setw(static_cast<int>(default_space)) << o->getDefault()
|
if (equalPos != std::string::npos)
|
||||||
<< std::setw(static_cast<int>(msg_space)) << o->getMessage()
|
{
|
||||||
<< (o->getRequired() ? "REQUIRED" : "NOT REQUIRED")
|
params_.insert({name.substr(0, equalPos), name.substr(equalPos + 1)});
|
||||||
<< std::endl;
|
continue;
|
||||||
}
|
}
|
||||||
return ret.str();
|
}
|
||||||
}
|
|
||||||
|
// if the option is unregistered and should be a multi-flag
|
||||||
bool isParsed(std::string const& name) {
|
if (1 == (args_[i].size() - name.size()) && // single dash
|
||||||
for (auto o : options) {
|
argh::parser::SINGLE_DASH_IS_MULTIFLAG & mode && // multi-flag mode
|
||||||
if (name == o->getName() && o->getParsed()) {
|
!is_param(name)) // unregistered
|
||||||
return true;
|
{
|
||||||
}
|
std::string keep_param;
|
||||||
}
|
|
||||||
return false;
|
if (!name.empty() && is_param(std::string(1ul, name.back()))) // last char is param
|
||||||
}
|
{
|
||||||
|
keep_param += name.back();
|
||||||
std::vector<std::string> missingRequired() {
|
name.resize(name.size() - 1);
|
||||||
std::vector<std::string> missing;
|
}
|
||||||
for (auto o : options) {
|
|
||||||
if (o->getRequired() && !o->getParsed())
|
for (auto const &c: name)
|
||||||
missing.push_back(o->getName());
|
{
|
||||||
}
|
flags_.emplace(std::string{c});
|
||||||
return missing;
|
}
|
||||||
}
|
|
||||||
|
if (!keep_param.empty())
|
||||||
bool load(std::string const& filename) {
|
{
|
||||||
std::ifstream ifs(filename);
|
name = keep_param;
|
||||||
if (!ifs.good()) { return false; }
|
}
|
||||||
int argc = 0;
|
else
|
||||||
std::vector<std::string> argv_str;
|
{
|
||||||
std::vector<char const*> argv;
|
continue; // do not consider other options for this arg
|
||||||
std::string arg;
|
}
|
||||||
while (std::getline(ifs, arg)) {
|
}
|
||||||
argv_str.push_back(arg);
|
|
||||||
++argc;
|
// any potential option will get as its value the next arg, unless that arg is an option too
|
||||||
}
|
// in that case it will be determined a flag.
|
||||||
for (int i = 0; i < argc; ++i) {
|
if (i == args_.size() - 1 || is_option(args_[i + 1]))
|
||||||
argv.push_back(argv_str[i].c_str());
|
{
|
||||||
}
|
flags_.emplace(name);
|
||||||
parse(argc, &*argv.begin());
|
continue;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
// if 'name' is a pre-registered option, then the next arg cannot be a free parameter to it
|
||||||
protected:
|
// is skipped otherwise we have 2 modes: PREFER_FLAG_FOR_UNREG_OPTION: a non-registered
|
||||||
|
// 'name' is determined a flag.
|
||||||
size_t getLongestName() {
|
// The following value (the next arg) will be a free
|
||||||
size_t ret = 0;
|
// parameter.
|
||||||
for (auto o : options) {
|
//
|
||||||
ret = std::max(ret, o->getName().length());
|
// PREFER_PARAM_FOR_UNREG_OPTION: a non-registered 'name' is determined a parameter, the
|
||||||
}
|
// next arg
|
||||||
return ret;
|
// will be the value of that option.
|
||||||
}
|
|
||||||
|
assert(!(mode & argh::parser::PREFER_FLAG_FOR_UNREG_OPTION) ||
|
||||||
size_t getLongestDefault() {
|
!(mode & argh::parser::PREFER_PARAM_FOR_UNREG_OPTION));
|
||||||
size_t ret = 0;
|
|
||||||
for (auto o : options) {
|
bool preferParam = mode & argh::parser::PREFER_PARAM_FOR_UNREG_OPTION;
|
||||||
ret = std::max(ret, o->getDefault().length());
|
|
||||||
}
|
if (is_param(name) || preferParam)
|
||||||
return ret;
|
{
|
||||||
}
|
params_.insert({name, args_[i + 1]});
|
||||||
|
++i; // skip next value, it is not a free parameter
|
||||||
size_t getLongestMessage() {
|
continue;
|
||||||
size_t ret = 0;
|
}
|
||||||
for (auto o : options) {
|
else
|
||||||
ret = std::max(ret, o->getMessage().length());
|
{
|
||||||
}
|
flags_.emplace(name);
|
||||||
return ret;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
std::vector<Option*> options;
|
|
||||||
char delim;
|
//////////////////////////////////////////////////////////////////////////
|
||||||
};
|
|
||||||
|
inline string_stream parser::bad_stream() const
|
||||||
|
{
|
||||||
|
string_stream bad;
|
||||||
|
bad.setstate(std::ios_base::failbit);
|
||||||
|
return bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool parser::is_number(std::string const &arg) const
|
||||||
|
{
|
||||||
|
// inefficient but simple way to determine if a string is a number (which can start with a '-')
|
||||||
|
std::istringstream istr(arg);
|
||||||
|
double number;
|
||||||
|
istr >> number;
|
||||||
|
return !(istr.fail() || istr.bad());
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool parser::is_option(std::string const &arg) const
|
||||||
|
{
|
||||||
|
assert(0 != arg.size());
|
||||||
|
if (is_number(arg))
|
||||||
|
return false;
|
||||||
|
return '-' == arg[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline std::string parser::trim_leading_dashes(std::string const &name) const
|
||||||
|
{
|
||||||
|
auto pos = name.find_first_not_of('-');
|
||||||
|
return std::string::npos != pos ? name.substr(pos) : name;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool argh::parser::got_flag(std::string const &name) const
|
||||||
|
{
|
||||||
|
return flags_.end() != flags_.find(trim_leading_dashes(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool argh::parser::is_param(std::string const &name) const
|
||||||
|
{
|
||||||
|
return registeredParams_.count(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool parser::operator[](std::string const &name) const { return got_flag(name); }
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline bool parser::operator[](std::initializer_list<char const *const> init_list) const
|
||||||
|
{
|
||||||
|
return std::any_of(init_list.begin(), init_list.end(),
|
||||||
|
[&](char const *const name) { return got_flag(name); });
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline std::string const &parser::operator[](size_t ind) const
|
||||||
|
{
|
||||||
|
if (ind < pos_args_.size())
|
||||||
|
return pos_args_[ind];
|
||||||
|
return empty_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline string_stream parser::operator()(std::string const &name) const
|
||||||
|
{
|
||||||
|
auto optIt = params_.find(trim_leading_dashes(name));
|
||||||
|
if (params_.end() != optIt)
|
||||||
|
return string_stream(optIt->second);
|
||||||
|
return bad_stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline string_stream parser::operator()(std::initializer_list<char const *const> init_list) const
|
||||||
|
{
|
||||||
|
for (auto &name: init_list)
|
||||||
|
{
|
||||||
|
auto optIt = params_.find(trim_leading_dashes(name));
|
||||||
|
if (params_.end() != optIt)
|
||||||
|
return string_stream(optIt->second);
|
||||||
|
}
|
||||||
|
return bad_stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename T> string_stream parser::operator()(std::string const &name, T &&def_val) const
|
||||||
|
{
|
||||||
|
auto optIt = params_.find(trim_leading_dashes(name));
|
||||||
|
if (params_.end() != optIt)
|
||||||
|
return string_stream(optIt->second);
|
||||||
|
|
||||||
|
std::ostringstream ostr;
|
||||||
|
ostr.precision(std::numeric_limits<long double>::max_digits10);
|
||||||
|
ostr << def_val;
|
||||||
|
return string_stream(ostr.str()); // use default
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// same as above but for a list of names. returns the first value to be found.
|
||||||
|
template <typename T>
|
||||||
|
string_stream parser::operator()(std::initializer_list<char const *const> init_list,
|
||||||
|
T &&def_val) const
|
||||||
|
{
|
||||||
|
for (auto &name: init_list)
|
||||||
|
{
|
||||||
|
auto optIt = params_.find(trim_leading_dashes(name));
|
||||||
|
if (params_.end() != optIt)
|
||||||
|
return string_stream(optIt->second);
|
||||||
|
}
|
||||||
|
std::ostringstream ostr;
|
||||||
|
ostr.precision(std::numeric_limits<long double>::max_digits10);
|
||||||
|
ostr << def_val;
|
||||||
|
return string_stream(ostr.str()); // use default
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline string_stream parser::operator()(size_t ind) const
|
||||||
|
{
|
||||||
|
if (pos_args_.size() <= ind)
|
||||||
|
return bad_stream();
|
||||||
|
|
||||||
|
return string_stream(pos_args_[ind]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <typename T> string_stream parser::operator()(size_t ind, T &&def_val) const
|
||||||
|
{
|
||||||
|
if (pos_args_.size() <= ind)
|
||||||
|
{
|
||||||
|
std::ostringstream ostr;
|
||||||
|
ostr.precision(std::numeric_limits<long double>::max_digits10);
|
||||||
|
ostr << def_val;
|
||||||
|
return string_stream(ostr.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return string_stream(pos_args_[ind]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void parser::add_param(std::string const &name)
|
||||||
|
{
|
||||||
|
registeredParams_.insert(trim_leading_dashes(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void parser::add_param(std::initializer_list<const char *const> init_list)
|
||||||
|
{
|
||||||
|
parser::add_params(init_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void parser::add_params(std::initializer_list<char const *const> init_list)
|
||||||
|
{
|
||||||
|
for (auto &name: init_list)
|
||||||
|
registeredParams_.insert(trim_leading_dashes(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void parser::add_params(const std::string &name) { parser::add_param(name); }
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline multimap_iteration_wrapper parser::params(std::string const &name) const
|
||||||
|
{
|
||||||
|
auto trimmed_name = trim_leading_dashes(name);
|
||||||
|
return multimap_iteration_wrapper(params_.lower_bound(trimmed_name),
|
||||||
|
params_.upper_bound(trimmed_name));
|
||||||
|
}
|
||||||
|
} // namespace argh
|
||||||
|
|
||||||
|
#endif /* BD0985AD_491A_464A_94D1_30155FF018C1 */
|
||||||
|
|
Loading…
Reference in a new issue