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 "**ProgramOptionMap::" #func \ 40 "** ATTEMPT TO SET OPTION WITH A NULL POINTER") 48 const std::string &msg,
bool silent, std::ostream &os)
53 os <<
"vSMC Program Option Warning\n";
54 os <<
"Option: " << oname <<
'\n';
55 os <<
"Message : " << msg << std::endl;
68 virtual bool is_bool()
const = 0;
71 const std::string &,
const std::string &, bool, std::ostream &) = 0;
78 bool set_value(
const std::string &oname,
const std::string &sval,
79 bool *dest,
bool silent, std::ostream &os)
81 const char *
const sptr = sval.c_str();
82 const std::size_t size = sval.size();
86 for (std::size_t i = 0; i != size; ++i) {
88 is_numb = is_numb && c >=
'0' && c <=
'9';
89 is_zero = is_zero && (c ==
'0');
100 is_true = is_true || std::strcmp(sptr,
"y") == 0;
101 is_true = is_true || std::strcmp(sptr,
"Y") == 0;
102 is_true = is_true || std::strcmp(sptr,
"yes") == 0;
103 is_true = is_true || std::strcmp(sptr,
"Yes") == 0;
104 is_true = is_true || std::strcmp(sptr,
"YES") == 0;
105 is_true = is_true || std::strcmp(sptr,
"t") == 0;
106 is_true = is_true || std::strcmp(sptr,
"T") == 0;
107 is_true = is_true || std::strcmp(sptr,
"true") == 0;
108 is_true = is_true || std::strcmp(sptr,
"True") == 0;
109 is_true = is_true || std::strcmp(sptr,
"TRUE") == 0;
115 bool is_false =
false;
116 is_false = is_false || std::strcmp(sptr,
"n") == 0;
117 is_false = is_false || std::strcmp(sptr,
"N") == 0;
118 is_false = is_false || std::strcmp(sptr,
"no") == 0;
119 is_false = is_false || std::strcmp(sptr,
"No") == 0;
120 is_false = is_false || std::strcmp(sptr,
"NO") == 0;
121 is_false = is_false || std::strcmp(sptr,
"f") == 0;
122 is_false = is_false || std::strcmp(sptr,
"F") == 0;
123 is_false = is_false || std::strcmp(sptr,
"false") == 0;
124 is_false = is_false || std::strcmp(sptr,
"False") == 0;
125 is_false = is_false || std::strcmp(sptr,
"FALSE") == 0;
132 oname,
"Failed to set value: " + sval, silent, os);
136 template <
typename T>
137 bool set_value(
const std::string &oname,
const std::string &sval, T *dest,
138 bool silent, std::ostream &os)
140 std::stringstream ss;
146 oname,
"Failed to set value: " + sval, silent, os);
150 *dest = std::move(tval);
167 bool set(
const std::string &oname,
const std::string &sval,
bool silent,
170 return set_value(oname, sval, &help_, silent, os);
177 return std::string(
"Print this help information");
180 std::string
default_str()
const {
return std::string(
"(false)"); }
184 bool help()
const {
return help_; }
192 template <
typename T>
197 : desc_(desc), default_(T()), has_default_(false)
201 template <
typename V>
203 : desc_(desc), default_(static_cast<T>(val)), has_default_(true)
207 bool is_bool()
const {
return std::is_same<T, bool>::value; }
213 return has_default_ ? default_val2str(default_) : std::string();
230 template <
typename U>
231 std::string default_val2str(
const U &val)
const 233 std::stringstream ss;
234 ss <<
'(' << val <<
')';
239 std::string default_val2str(
bool val)
const 241 return val ? std::string(
"(true)") : std::string(
"(false)");
247 template <
typename T>
256 template <
typename V>
264 bool set(
const std::string &oname,
const std::string &sval,
bool silent,
267 return this->
set_value(oname, sval, ptr_, silent, os);
280 template <
typename T>
289 template <
typename V>
297 bool set(
const std::string &oname,
const std::string &sval,
bool silent,
300 bool success = this->
set_value(oname, sval, &val_, silent, os);
303 ptr_->push_back(val_);
310 bool success = this->set_value_default(&val_);
313 ptr_->push_back(val_);
322 std::vector<T> *
const ptr_;
329 using option_map_type =
330 std::map<std::string, std::pair<ProgramOption *, std::size_t>>;
331 using option_list_type =
332 std::list<std::pair<std::string, const ProgramOption *>>;
337 , auto_help_(auto_help)
340 option_map_[
"--help"] = std::make_pair(help_ptr_, 0);
341 option_list_.push_back(std::make_pair(
"--help", help_ptr_));
345 : silent_(other.silent_)
346 , auto_help_(other.auto_help_)
347 , option_map_(other.option_map_)
348 , option_list_(other.option_list_)
350 for (option_map_type::iterator iter = option_map_.begin();
351 iter != option_map_.end(); ++iter) {
352 if (iter->second.first)
353 iter->second.first = iter->second.first->clone();
359 if (
this != &other) {
360 silent_ = other.silent_;
361 auto_help_ = other.auto_help_;
362 for (option_map_type::iterator iter = option_map_.begin();
363 iter != option_map_.end(); ++iter) {
364 if (iter->second.first)
365 delete iter->second.first;
368 option_map_ = other.option_map_;
369 option_list_ = other.option_list_;
371 for (option_map_type::iterator iter = option_map_.begin();
372 iter != option_map_.end(); ++iter) {
373 if (iter->second.first)
374 iter->second.first = iter->second.first->clone();
382 : silent_(other.silent_)
383 , auto_help_(other.auto_help_)
384 , help_ptr_(other.help_ptr_)
385 , option_map_(
std::move(other.option_map_))
386 , option_list_(
std::move(other.option_list_))
388 other.help_ptr_ =
nullptr;
389 other.option_map_.clear();
390 other.option_list_.clear();
395 if (
this != &other) {
396 silent_ = other.silent_;
397 help_ptr_ = other.help_ptr_;
398 option_map_ = std::move(other.option_map_);
399 option_list_ = std::move(other.option_list_);
400 other.help_ptr_ =
nullptr;
401 other.option_map_.clear();
402 other.option_list_.clear();
410 for (option_map_type::iterator iter = option_map_.begin();
411 iter != option_map_.end(); ++iter) {
412 if (iter->second.first !=
nullptr)
413 delete iter->second.first;
423 template <
typename T>
425 const std::string &name,
const std::string &desc, T *ptr)
428 const std::string oname(
"--" + name);
430 add_option(oname, optr);
436 template <
typename T,
typename V>
438 const std::string &name,
const std::string &desc, T *ptr, V val)
441 const std::string oname(
"--" + name);
443 add_option(oname, optr);
449 template <
typename T>
451 const std::string &name,
const std::string &desc, std::vector<T> *ptr)
454 const std::string oname(
"--" + name);
456 add_option(oname, optr);
462 template <
typename T,
typename V>
464 std::vector<T> *ptr, V val)
467 const std::string oname(
"--" + name);
469 add_option(oname, optr);
476 const std::string oname(
"--" + name);
477 option_map_type::iterator iter = option_map_.find(oname);
478 if (iter != option_map_.end()) {
479 if (iter->second.first !=
nullptr)
480 delete iter->second.first;
481 option_map_.erase(iter);
482 option_list_type::iterator liter = option_list_find(oname);
483 option_list_.erase(liter);
500 void process(
int argc,
const char **argv, std::ostream &os = std::cout)
503 std::vector<std::string> arg_vector;
504 arg_vector.reserve(static_cast<std::size_t>(argc));
505 for (
int i = 0; i != argc; ++i) {
506 arg = process_arg(argv[i]);
508 arg_vector.push_back(arg);
510 process_arg_vector(arg_vector, os);
514 void process(
int argc,
char **argv, std::ostream &os = std::cout)
517 std::vector<std::string> arg_vector;
518 arg_vector.reserve(static_cast<std::size_t>(argc));
519 for (
int i = 0; i != argc; ++i) {
520 arg = process_arg(argv[i]);
522 arg_vector.push_back(arg);
524 process_arg_vector(arg_vector, os);
530 std::size_t len[2] = {0, 0};
531 std::vector<std::string> vec[3];
532 for (option_list_type::const_iterator liter = option_list_.begin();
533 liter != option_list_.end(); ++liter) {
534 vec[0].push_back(liter->first);
535 vec[1].push_back(liter->second->description());
536 vec[2].push_back(liter->second->default_str());
537 if (len[0] < vec[0].back().size())
538 len[0] = vec[0].back().size();
539 if (len[1] < vec[1].back().size())
540 len[1] = vec[1].back().size();
544 for (std::size_t i = 0; i != vec[0].size(); ++i) {
545 os << vec[0][i] << std::string(len[0] - vec[0][i].size(),
' ');
546 os << vec[1][i] << std::string(len[1] - vec[1][i].size(),
' ');
547 os << vec[2][i] << std::endl;
552 std::size_t
count(
const std::string &name)
const 554 option_map_type::const_iterator iter = option_map_.find(
"--" + name);
555 if (iter != option_map_.end())
556 return iter->second.second;
564 option_map_type::const_iterator iter = option_map_.find(
"--" + name);
565 if (iter != option_map_.end())
566 return iter->second.first;
574 option_map_type::const_iterator iter = option_map_.find(
"--" + name);
575 if (iter != option_map_.end())
576 return iter->second.first;
583 void silent(
bool flag) { silent_ = flag; }
593 option_map_type option_map_;
594 option_list_type option_list_;
596 option_list_type::iterator option_list_find(
const std::string &oname)
598 option_list_type::iterator liter = option_list_.begin();
599 for (; liter != option_list_.end(); ++liter) {
600 if (liter->first == oname)
607 void add_option(
const std::string &oname,
ProgramOption *optr)
609 std::pair<option_map_type::iterator, bool> insert =
610 option_map_.insert(std::make_pair(oname, std::make_pair(optr, 0)));
612 option_list_.push_back(std::make_pair(oname, optr));
614 if (insert.first->second.first !=
nullptr)
615 delete insert.first->second.first;
616 insert.first->second.first = optr;
617 option_list_type::iterator liter = option_list_find(oname);
618 liter->second = optr;
622 void process_arg_vector(
623 std::vector<std::string> &arg_vector, std::ostream &os)
625 std::string option_value;
626 const std::vector<std::string> option_value_vec;
627 std::vector<std::pair<std::string, std::vector<std::string>>>
629 std::vector<std::string>::iterator aiter = arg_vector.begin();
630 while (aiter != arg_vector.end() && !is_option(*aiter))
632 while (aiter != arg_vector.end()) {
633 option_vector.push_back(std::make_pair(*aiter, option_value_vec));
634 std::vector<std::string> &value = option_vector.back().second;
636 while (aiter != arg_vector.end() && !is_option(*aiter)) {
637 value.push_back(*aiter);
642 const std::string sval_true(
"1");
643 for (std::vector<std::pair<std::string,
644 std::vector<std::string>>>::iterator iter =
645 option_vector.begin();
646 iter != option_vector.end(); ++iter) {
647 option_map_type::iterator miter = option_map_.find(iter->first);
648 if (miter == option_map_.end()) {
650 iter->first,
"Unknown option", silent_, os);
655 const std::size_t vsize = iter->second.size();
656 if (vsize == 0 && miter->second.first->is_bool()) {
657 proc = process_option(miter, sval_true, os);
658 }
else if (vsize == 0) {
660 miter->first,
"Value not found", silent_, os);
661 }
else if (!miter->second.first->is_vector()) {
662 option_value.clear();
663 for (std::size_t i = 0; i != vsize - 1; ++i)
664 option_value += iter->second[i] +
' ';
665 option_value += iter->second[vsize - 1];
666 proc = process_option(miter, option_value, os);
668 for (std::size_t i = 0; i != vsize; ++i)
669 proc = process_option(miter, iter->second[i], os) || proc;
672 ++miter->second.second;
675 for (option_map_type::iterator iter = option_map_.begin();
676 iter != option_map_.end(); ++iter) {
677 if (iter->second.second == 0)
678 if (iter->second.first->set_default())
679 iter->second.second = 1;
682 if (auto_help_ && help_ptr_->
help())
686 std::string process_arg(
const char *arg)
const 688 std::size_t s = std::strlen(arg);
690 while (e != 0 && (arg[e - 1] ==
' ' || arg[e - 1] ==
','))
693 return std::string(arg, arg + e);
696 bool process_option(option_map_type::iterator iter,
697 const std::string &sval, std::ostream &os)
704 return iter->second.first->set(iter->first, sval, silent_, os);
707 bool is_option(
const std::string &str)
const 724 #endif // VSMC_UTILITY_PROGRAM_OPTION_HPP ProgramOption & operator=(const ProgramOption &)
virtual bool set_default()=0
ProgramOptionMap(bool silent=false, bool auto_help=true)
std::string default_str() const
virtual ProgramOption * clone() const =0
ProgramOption * option(const std::string &name)
Get the underlying option object.
ProgramOptionMap & add(const std::string &name, const std::string &desc, T *ptr)
Add an option with a single value.
ProgramOptionMap & operator=(const ProgramOptionMap &other)
ProgramOptionDefault(const std::string &desc)
ProgramOption * clone() const
#define VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, func)
std::string description() const
ProgramOption(const ProgramOption &)
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)
ProgramOptionMap & operator=(ProgramOptionMap &&other)
ProgramOptionDefault(const std::string &desc, V val)
ProgramOptionVector(const std::string &desc, std::vector< T > *ptr)
virtual bool is_bool() const =0
ProgramOption * clone() const
Option with multiple values.
void program_option_warning(const std::string &oname, const std::string &msg, bool silent, std::ostream &os)
Program option warning messages.
Program option base class.
ProgramOptionMap(const ProgramOptionMap &other)
bool set_value(const std::string &oname, const std::string &sval, bool *dest, bool silent, std::ostream &os)
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.
virtual bool is_vector() const =0
virtual std::string description() const =0
virtual std::string default_str() const =0
ProgramOption * clone() const
const ProgramOption * option(const std::string &name) const
Get the underlying option object.
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_default(T *dest)
bool set_value(const std::string &oname, const std::string &sval, T *dest, bool silent, std::ostream &os)
ProgramOptionMap(ProgramOptionMap &&other)
std::string description() const
void auto_help(bool flag)
Set the auto_help flag, if true, help information is printed automatically when the --help option is ...