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