32 #ifndef VSMC_UTILITY_PROGRAM_OPTION_HPP 33 #define VSMC_UTILITY_PROGRAM_OPTION_HPP 38 #pragma clang diagnostic push 39 #pragma clang diagnostic ignored "-Wweak-vtables" 42 #define VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, func) \ 43 VSMC_RUNTIME_ASSERT((ptr != nullptr), \ 44 "**ProgramOption::" #func \ 45 "** ATTEMPT TO SET OPTION WITH A NULL POINTER") 59 os <<
"vSMC Program Option Warning\n";
60 os <<
"Option: --" << name <<
'\n';
61 os <<
"Message : " << msg << std::endl;
76 virtual bool is_bool()
const = 0;
77 virtual bool is_vector()
const = 0;
79 const std::string &,
const std::string &, bool,
std::ostream &) = 0;
80 virtual bool set_default() = 0;
81 virtual std::string description()
const = 0;
82 virtual std::string default_str()
const = 0;
85 bool set_value(
const std::string &name,
const std::string &sval,
88 const char *
const sptr = sval.c_str();
89 const std::size_t size = sval.size();
93 for (std::size_t i = 0; i != size; ++i) {
95 is_numb = is_numb && c >=
'0' && c <=
'9';
96 is_zero = is_zero && (c ==
'0');
101 }
else if (is_numb) {
106 bool is_true =
false;
107 is_true = is_true || std::strcmp(sptr,
"y") == 0;
108 is_true = is_true || std::strcmp(sptr,
"Y") == 0;
109 is_true = is_true || std::strcmp(sptr,
"yes") == 0;
110 is_true = is_true || std::strcmp(sptr,
"Yes") == 0;
111 is_true = is_true || std::strcmp(sptr,
"YES") == 0;
112 is_true = is_true || std::strcmp(sptr,
"t") == 0;
113 is_true = is_true || std::strcmp(sptr,
"T") == 0;
114 is_true = is_true || std::strcmp(sptr,
"true") == 0;
115 is_true = is_true || std::strcmp(sptr,
"True") == 0;
116 is_true = is_true || std::strcmp(sptr,
"TRUE") == 0;
122 bool is_false =
false;
123 is_false = is_false || std::strcmp(sptr,
"n") == 0;
124 is_false = is_false || std::strcmp(sptr,
"N") == 0;
125 is_false = is_false || std::strcmp(sptr,
"no") == 0;
126 is_false = is_false || std::strcmp(sptr,
"No") == 0;
127 is_false = is_false || std::strcmp(sptr,
"NO") == 0;
128 is_false = is_false || std::strcmp(sptr,
"f") == 0;
129 is_false = is_false || std::strcmp(sptr,
"F") == 0;
130 is_false = is_false || std::strcmp(sptr,
"false") == 0;
131 is_false = is_false || std::strcmp(sptr,
"False") == 0;
132 is_false = is_false || std::strcmp(sptr,
"FALSE") == 0;
139 name,
"Failed to set value: " + sval, silent, os);
143 bool set_value(
const std::string &,
const std::string &sval,
151 template <
typename T>
152 bool set_value(
const std::string &name,
const std::string &sval, T *dest,
155 std::stringstream ss;
161 name,
"Failed to set value: " + sval, silent, os);
165 *dest = std::move(tval);
182 bool set(
const std::string &name,
const std::string &sval,
bool silent,
185 return set_value(name, sval, &help_, silent, os);
192 return std::string(
"Print this help information");
195 std::string
default_str()
const {
return std::string(
"(false)"); }
197 bool help()
const {
return help_; }
205 template <
typename T>
210 : desc_(desc), default_(T()), has_default_(false)
214 template <
typename V>
216 : desc_(desc), default_(static_cast<T>(val)), has_default_(true)
220 bool is_bool()
const {
return std::is_same<T, bool>::value; }
226 return has_default_ ? default_val2str(default_) : std::string();
243 template <
typename U>
244 std::string default_val2str(
const U &val)
const 246 std::stringstream ss;
247 ss <<
'(' << val <<
')';
252 std::string default_val2str(
bool val)
const 254 return val ? std::string(
"(true)") : std::string(
"(false)");
260 template <
typename T>
269 template <
typename V>
277 bool set(
const std::string &name,
const std::string &sval,
bool silent,
280 return this->set_value(name, sval, ptr_, silent, os);
291 template <
typename T,
typename Alloc>
300 template <
typename V>
302 const std::string &desc, std::vector<T, Alloc> *ptr, V val)
309 bool set(
const std::string &name,
const std::string &sval,
bool silent,
313 bool success = this->set_value(name, sval, &val, silent, os);
315 ptr_->push_back(val);
323 bool success = this->set_value_default(&val);
325 ptr_->push_back(val);
331 std::vector<T, Alloc> *
const ptr_;
342 add_option(
"help", help_ptr_);
351 template <
typename T>
353 const std::string &name,
const std::string &desc, T *ptr)
362 template <
typename T,
typename V>
364 const std::string &name,
const std::string &desc, T *ptr, V val)
373 template <
typename T,
typename Alloc>
375 std::vector<T, Alloc> *ptr)
384 template <
typename T,
typename Alloc,
typename V>
386 std::vector<T, Alloc> *ptr, V val)
390 return add_option(name,
396 auto iter = option_find(name);
397 if (iter != option_vec_.end())
398 option_vec_.erase(iter);
414 int argc,
const char *
const *argv,
std::ostream &os = std::cout)
418 arg_vector.reserve(static_cast<std::size_t>(argc));
419 for (
int i = 0; i != argc; ++i) {
420 arg = process_arg(argv[i]);
422 arg_vector.push_back(arg);
424 process_arg_vector(arg_vector, os);
432 arg_vector.reserve(static_cast<std::size_t>(argc));
433 for (
int i = 0; i != argc; ++i) {
434 arg = process_arg(argv[i]);
436 arg_vector.push_back(arg);
438 process_arg_vector(arg_vector, os);
444 std::size_t len[2] = {0, 0};
446 for (
const auto &option : option_vec_) {
447 str[0].push_back(
"--" + option.name);
448 str[1].push_back(option.ptr->description());
449 str[2].push_back(option.ptr->default_str());
450 len[0] = std::max(len[0], str[0].back().size());
451 len[1] = std::max(len[1], str[1].back().size());
455 for (std::size_t i = 0; i != str[0].size(); ++i) {
456 os << str[0][i] << std::string(len[0] - str[0][i].size(),
' ');
457 os << str[1][i] << std::string(len[1] - str[1][i].size(),
' ');
458 os << str[2][i] << std::endl;
463 std::size_t
count(
const std::string &name)
const 465 auto iter = option_find(name);
466 if (iter != option_vec_.end())
472 bool help() {
return help_ptr_->help(); }
475 std::shared_ptr<ProgramOption>
option(
const std::string &name)
477 auto iter = option_find(name);
478 if (iter != option_vec_.end())
480 return std::shared_ptr<ProgramOption>(
481 static_cast<ProgramOption *>(
nullptr));
485 std::shared_ptr<const ProgramOption>
option(
const std::string &name)
const 487 auto iter = option_find(name);
488 if (iter != option_vec_.end())
490 return std::shared_ptr<const ProgramOption>(
491 static_cast<const ProgramOption *>(
nullptr));
496 void silent(
bool flag) { silent_ = flag; }
501 std::shared_ptr<ProgramOption> ptr;
508 std::shared_ptr<ProgramOptionHelp> help_ptr_;
509 option_vec_type option_vec_;
511 option_vec_type::iterator option_find(
const std::string &name)
513 auto iter = option_vec_.begin();
514 for (; iter != option_vec_.end(); ++iter)
515 if (iter->name == name)
521 option_vec_type::const_iterator option_find(
const std::string &name)
const 523 auto iter = option_vec_.begin();
524 for (; iter != option_vec_.end(); ++iter)
525 if (iter->name == name)
532 const std::string &name, std::shared_ptr<ProgramOption> optr)
534 option_type option = {name, optr, 0};
535 auto iter = option_find(name);
536 if (iter != option_vec_.end())
539 option_vec_.push_back(option);
548 auto aiter = arg_vector.begin();
549 while (aiter != arg_vector.end() && !is_option(*aiter))
551 while (aiter != arg_vector.end()) {
552 std::string name(aiter->begin() + 2, aiter->end());
555 while (aiter != arg_vector.end() && !is_option(*aiter)) {
556 svals.push_back(*aiter);
559 name_svals.push_back(std::make_pair(name, svals));
562 const std::string sval_true(
"1");
563 for (
auto &nsv : name_svals) {
564 auto iter = option_find(nsv.first);
565 if (iter == option_vec_.end()) {
567 nsv.first,
"Unknown option", silent_, os);
572 if (nsv.second.size() == 0 && iter->ptr->is_bool()) {
573 proc = process_option(iter, sval_true, os);
574 }
else if (nsv.second.size() == 0) {
576 nsv.first,
"No value found", silent_, os);
577 }
else if (iter->ptr->is_vector()) {
578 for (
const auto &sval : nsv.second)
579 proc = process_option(iter, sval, os);
581 proc = process_option(iter, nsv.second.back(), os) || proc;
587 for (
auto &option : option_vec_)
588 if (option.count == 0)
589 if (option.ptr->set_default())
596 std::string process_arg(
const char *arg)
const 598 std::size_t s = std::strlen(arg);
600 while (e != 0 && (arg[e - 1] ==
' ' || arg[e - 1] ==
','))
603 return std::string(arg, arg + e);
606 bool process_option(option_vec_type::iterator iter,
611 iter->name,
"No value found", silent_, os);
614 return iter->ptr->set(iter->name, sval, silent_, os);
617 bool is_option(
const std::string &str)
const 635 #pragma clang diagnostic pop 638 #endif // VSMC_UTILITY_PROGRAM_OPTION_HPP std::vector< T, Alloc > Vector
std::vector with Allocator as default allocator
ProgramOptionMap & add(const std::string &name, const std::string &desc, std::vector< T, Alloc > *ptr)
Add an option with multiple value.
std::string default_str() const
ProgramOptionVector(const std::string &desc, std::vector< T, Alloc > *ptr, V val)
std::basic_ostream< CharT, Traits > & ostream(std::basic_ostream< CharT, Traits > &os, const std::array< T, N > &ary)
ProgramOptionMap & add(const std::string &name, const std::string &desc, std::vector< T, Alloc > *ptr, V val)
Add an option with multiple value, with a default value.
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 &)
ProgramOptionVector(const std::string &desc, std::vector< T, Alloc > *ptr)
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...
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)
bool help()
If the "help" option is processed and set to true.
Option with multiple values.
void process(int argc, const char *const *argv, std::ostream &os=std::cout)
Process the options.
Option with a single value.
std::string default_str() const
void print_help(std::ostream &os=std::cout) const
Print help information for each option.
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.
bool set_value(const std::string &name, const std::string &sval, T *dest, bool silent, std::ostream &os)
bool set_value_default(T *dest)
void process(int argc, char *const *argv, std::ostream &os=std::cout)
Process the options.
ProgramOptionMap(bool silent=false)
std::string description() const