32 #ifndef VSMC_UTILITY_PROGRAM_OPTION_HPP    33 #define VSMC_UTILITY_PROGRAM_OPTION_HPP    37 #define VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, func)         \    38     VSMC_RUNTIME_ASSERT((ptr != nullptr),                                     \    39         "**ProgramOption::" #func                                             \    40         "** ATTEMPT TO SET OPTION WITH A NULL POINTER")    49     const std::string &msg, 
bool silent, std::ostream &os)
    54     os << 
"vSMC Program Option Warning\n";
    55     os << 
"Option: --" << name << 
'\n';
    56     os << 
"Message : " << msg << std::endl;
    71     virtual bool is_bool() 
const = 0;
    72     virtual bool is_vector() 
const = 0;
    74         const std::string &, 
const std::string &, bool, std::ostream &) = 0;
    75     virtual bool set_default() = 0;
    76     virtual std::string description() 
const = 0;
    77     virtual std::string default_str() 
const = 0;
    80     bool set_value(
const std::string &name, 
const std::string &sval,
    81         bool *dest, 
bool silent, std::ostream &os)
    83         const char *
const sptr = sval.c_str();
    84         const std::size_t size = sval.size();
    88         for (std::size_t i = 0; i != size; ++i) {
    90             is_numb = is_numb && c >= 
'0' && c <= 
'9';
    91             is_zero = is_zero && (c == 
'0');
   101         bool is_true = 
false;
   102         is_true = is_true || std::strcmp(sptr, 
"y") == 0;
   103         is_true = is_true || std::strcmp(sptr, 
"Y") == 0;
   104         is_true = is_true || std::strcmp(sptr, 
"yes") == 0;
   105         is_true = is_true || std::strcmp(sptr, 
"Yes") == 0;
   106         is_true = is_true || std::strcmp(sptr, 
"YES") == 0;
   107         is_true = is_true || std::strcmp(sptr, 
"t") == 0;
   108         is_true = is_true || std::strcmp(sptr, 
"T") == 0;
   109         is_true = is_true || std::strcmp(sptr, 
"true") == 0;
   110         is_true = is_true || std::strcmp(sptr, 
"True") == 0;
   111         is_true = is_true || std::strcmp(sptr, 
"TRUE") == 0;
   117         bool is_false = 
false;
   118         is_false = is_false || std::strcmp(sptr, 
"n") == 0;
   119         is_false = is_false || std::strcmp(sptr, 
"N") == 0;
   120         is_false = is_false || std::strcmp(sptr, 
"no") == 0;
   121         is_false = is_false || std::strcmp(sptr, 
"No") == 0;
   122         is_false = is_false || std::strcmp(sptr, 
"NO") == 0;
   123         is_false = is_false || std::strcmp(sptr, 
"f") == 0;
   124         is_false = is_false || std::strcmp(sptr, 
"F") == 0;
   125         is_false = is_false || std::strcmp(sptr, 
"false") == 0;
   126         is_false = is_false || std::strcmp(sptr, 
"False") == 0;
   127         is_false = is_false || std::strcmp(sptr, 
"FALSE") == 0;
   134             name, 
"Failed to set value: " + sval, silent, os);
   138     bool set_value(
const std::string &, 
const std::string &sval,
   139         std::string *dest, 
bool, std::ostream &)
   146     template <
typename T>
   147     bool set_value(
const std::string &name, 
const std::string &sval, T *dest,
   148         bool silent, std::ostream &os)
   150         std::stringstream ss;
   156                 name, 
"Failed to set value: " + sval, silent, os);
   160         *dest = std::move(tval);
   177     bool set(
const std::string &name, 
const std::string &sval, 
bool silent,
   180         return set_value(name, sval, &help_, silent, os);
   187         return std::string(
"Print this help information");
   190     std::string 
default_str()
 const { 
return std::string(
"(false)"); }
   192     bool help()
 const { 
return help_; }
   200 template <
typename T>
   205         : desc_(desc), default_(T()), has_default_(false)
   209     template <
typename V>
   211         : desc_(desc), default_(static_cast<T>(val)), has_default_(true)
   215     bool is_bool()
 const { 
return std::is_same<T, bool>::value; }
   221         return has_default_ ? default_val2str(default_) : std::string();
   238     template <
typename U>
   239     std::string default_val2str(
const U &val)
 const   241         std::stringstream ss;
   242         ss << 
'(' << val << 
')';
   247     std::string default_val2str(
bool val)
 const   249         return val ? std::string(
"(true)") : std::string(
"(false)");
   255 template <
typename T>
   264     template <
typename V>
   272     bool set(
const std::string &name, 
const std::string &sval, 
bool silent,
   275         return this->set_value(name, sval, ptr_, silent, os);
   286 template <
typename T>
   295     template <
typename V>
   303     bool set(
const std::string &name, 
const std::string &sval, 
bool silent,
   307         bool success = this->set_value(name, sval, &val, silent, os);
   309             ptr_->push_back(val);
   317         bool success = this->set_value_default(&val);
   319             ptr_->push_back(val);
   325     std::vector<T> *
const ptr_;
   336         add_option(
"help", help_ptr_);
   345     template <
typename T>
   347         const std::string &name, 
const std::string &desc, T *ptr)
   356     template <
typename T, 
typename V>
   358         const std::string &name, 
const std::string &desc, T *ptr, V val)
   367     template <
typename T>
   369         const std::string &name, 
const std::string &desc, std::vector<T> *ptr)
   378     template <
typename T, 
typename V>
   380         std::vector<T> *ptr, V val)
   390         auto iter = option_find(name);
   391         if (iter != option_vec_.end())
   392             option_vec_.erase(iter);
   407     void process(
int argc, 
const char **argv, std::ostream &os = std::cout)
   411         arg_vector.reserve(static_cast<std::size_t>(argc));
   412         for (
int i = 0; i != argc; ++i) {
   413             arg = process_arg(argv[i]);
   415                 arg_vector.push_back(arg);
   417         process_arg_vector(arg_vector, os);
   421     void process(
int argc, 
char **argv, std::ostream &os = std::cout)
   425         arg_vector.reserve(static_cast<std::size_t>(argc));
   426         for (
int i = 0; i != argc; ++i) {
   427             arg = process_arg(argv[i]);
   429                 arg_vector.push_back(arg);
   431         process_arg_vector(arg_vector, os);
   437         std::size_t len[2] = {0, 0};
   439         for (
const auto &option : option_vec_) {
   440             str[0].push_back(
"--" + std::get<0>(option));
   441             str[1].push_back(std::get<1>(option)->description());
   442             str[2].push_back(std::get<1>(option)->default_str());
   443             len[0] = std::max(len[0], str[0].back().size());
   444             len[1] = std::max(len[1], str[1].back().size());
   448         for (std::size_t i = 0; i != str[0].size(); ++i) {
   449             os << str[0][i] << std::string(len[0] - str[0][i].size(), 
' ');
   450             os << str[1][i] << std::string(len[1] - str[1][i].size(), 
' ');
   451             os << str[2][i] << std::endl;
   456     std::size_t 
count(
const std::string &name)
 const   458         auto iter = option_find(name);
   459         if (iter != option_vec_.end())
   460             return std::get<2>(*iter);
   465     bool help() { 
return help_ptr_->help(); }
   468     std::shared_ptr<ProgramOption> 
option(
const std::string &name)
   470         auto iter = option_find(name);
   471         if (iter != option_vec_.end())
   472             return std::get<1>(*iter);
   473         return std::shared_ptr<ProgramOption>(
   478     std::shared_ptr<const ProgramOption> 
option(
const std::string &name)
 const   480         auto iter = option_find(name);
   481         if (iter != option_vec_.end())
   482             return std::get<1>(*iter);
   483         return std::shared_ptr<const ProgramOption>(
   489     void silent(
bool flag) { silent_ = flag; }
   492     using option_vec_type = 
Vector<
   493         std::tuple<std::string, std::shared_ptr<ProgramOption>, std::size_t>>;
   496     std::shared_ptr<ProgramOptionHelp> help_ptr_;
   497     option_vec_type option_vec_;
   499     option_vec_type::iterator option_find(
const std::string &name)
   501         auto iter = option_vec_.begin();
   502         for (; iter != option_vec_.end(); ++iter)
   503             if (std::get<0>(*iter) == name)
   509     option_vec_type::const_iterator option_find(
const std::string &name)
 const   511         auto iter = option_vec_.begin();
   512         for (; iter != option_vec_.end(); ++iter)
   513             if (std::get<0>(*iter) == name)
   520         const std::string &name, std::shared_ptr<ProgramOption> optr)
   522         auto option = std::make_tuple(name, optr, 0);
   523         auto iter = option_find(name);
   524         if (iter != option_vec_.end())
   527             option_vec_.push_back(option);
   532     void process_arg_vector(
   533         std::vector<std::string> &arg_vector, std::ostream &os)
   537         auto aiter = arg_vector.begin();
   538         while (aiter != arg_vector.end() && !is_option(*aiter))
   540         while (aiter != arg_vector.end()) {
   541             std::string name(aiter->begin() + 2, aiter->end());
   544             while (aiter != arg_vector.end() && !is_option(*aiter)) {
   545                 svals.push_back(*aiter);
   548             name_svals.push_back(std::make_pair(name, svals));
   551         const std::string sval_true(
"1");
   552         for (
auto &nsv : name_svals) {
   553             auto iter = option_find(nsv.first);
   554             if (iter == option_vec_.end()) {
   556                     nsv.first, 
"Unknown option", silent_, os);
   561             if (nsv.second.size() == 0 && std::get<1>(*iter)->is_bool()) {
   562                 proc = process_option(iter, sval_true, os);
   563             } 
else if (nsv.second.size() == 0) {
   565                     nsv.first, 
"No value found", silent_, os);
   566             } 
else if (std::get<1>(*iter)->is_vector()) {
   567                 for (
const auto &sval : nsv.second)
   568                     proc = process_option(iter, sval, os);
   570                 proc = process_option(iter, nsv.second.back(), os) || proc;
   573                 ++std::get<2>(*iter);
   576         for (
auto &option : option_vec_)
   577             if (std::get<2>(option) == 0)
   578                 if (std::get<1>(option)->set_default())
   579                     std::get<2>(option) = 1;
   585     std::string process_arg(
const char *arg)
 const   587         std::size_t s = std::strlen(arg);
   589         while (e != 0 && (arg[e - 1] == 
' ' || arg[e - 1] == 
','))
   592         return std::string(arg, arg + e);
   595     bool process_option(option_vec_type::iterator iter,
   596         const std::string &sval, std::ostream &os)
   600                 std::get<0>(*iter), 
"No value found", silent_, os);
   603         return std::get<1>(*iter)->set(std::get<0>(*iter), sval, silent_, os);
   606     bool is_option(
const std::string &str)
 const   623 #endif // VSMC_UTILITY_PROGRAM_OPTION_HPP 
typename std::conditional< std::is_scalar< T >::value, AlignedVector< T >, std::vector< T >>::type Vector
AlignedVector for scalar type and std::vector for others. 
 
std::string default_str() const 
 
ProgramOptionMap & add(const std::string &name, const std::string &desc, T *ptr)
Add an option with a single value. 
 
bool set_value(const std::string &, const std::string &sval, std::string *dest, bool, std::ostream &)
 
ProgramOptionDefault(const std::string &desc)
 
#define VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, func)              
 
std::string description() const 
 
std::shared_ptr< ProgramOption > option(const std::string &name)
Get the underlying option object. 
 
void silent(bool flag)
Set the silent flag, if true, no warning messages will be printed for unknown options etc...
 
void process(int argc, const char **argv, std::ostream &os=std::cout)
Process the options. 
 
ProgramOptionScalar(const std::string &desc, T *ptr)
 
ProgramOptionScalar(const std::string &desc, T *ptr, V val)
 
bool set_value(const std::string &name, const std::string &sval, bool *dest, bool silent, std::ostream &os)
 
void program_option_warning(const std::string &name, const std::string &msg, bool silent, std::ostream &os)
 
std::shared_ptr< const ProgramOption > option(const std::string &name) const 
Get the underlying option object. 
 
ProgramOptionDefault(const std::string &desc, V val)
 
ProgramOptionVector(const std::string &desc, std::vector< T > *ptr)
 
bool help()
If the "help" option is processed and set to true. 
 
Option with multiple values. 
 
Option with a single value. 
 
ProgramOptionMap & add(const std::string &name, const std::string &desc, std::vector< T > *ptr, V val)
Add an option with multiple value, with a default value. 
 
std::string default_str() const 
 
void print_help(std::ostream &os=std::cout) const 
Print help information for each option. 
 
ProgramOptionMap & add(const std::string &name, const std::string &desc, std::vector< T > *ptr)
Add an option with multiple value. 
 
void process(int argc, char **argv, std::ostream &os=std::cout)
Process the options. 
 
Option with a default value. 
 
std::size_t count(const std::string &name) const 
Count the number of successful processing of an option. 
 
void add(std::size_t n, const float *a, const float *b, float *y)
 
ProgramOptionMap & add(const std::string &name, const std::string &desc, T *ptr, V val)
Add an option with a single value, with a default value. 
 
ProgramOptionVector(const std::string &desc, std::vector< T > *ptr, V val)
 
bool set_value(const std::string &name, const std::string &sval, T *dest, bool silent, std::ostream &os)
 
bool set_value_default(T *dest)
 
ProgramOptionMap(bool silent=false)
 
std::string description() const