208 #ifndef VSMC_UTILITY_PROGRAM_OPTION_HPP
209 #define VSMC_UTILITY_PROGRAM_OPTION_HPP
213 #define VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, func) \
214 VSMC_RUNTIME_ASSERT((ptr != VSMC_NULLPTR), \
215 ("**ProgramOptionMap::"#func \
216 "** ATTEMPT TO SET OPTION WITH A NULL POINTER"))
223 const std::string &msg,
bool silent, std::ostream &os)
228 os <<
"vSMC Program Option Warning\n";
229 os <<
"Option: " << oname <<
'\n';
230 os <<
"Message : " << msg << std::endl;
244 virtual bool is_bool ()
const = 0;
246 virtual bool set (
const std::string &,
const std::string &,
bool,
255 bool set_value (
const std::string &oname,
const std::string &sval,
256 bool *dest,
bool silent, std::ostream &os)
258 const char *
const sptr = sval.c_str();
259 const std::size_t size = sval.size();
263 for (std::size_t i = 0; i != size; ++i) {
265 is_numb = is_numb && c >=
'0' && c <=
'9';
266 is_zero = is_zero && (c ==
'0');
271 }
else if (is_numb) {
276 bool is_true =
false;
277 is_true = is_true || std::strcmp(sptr,
"y") == 0;
278 is_true = is_true || std::strcmp(sptr,
"Y") == 0;
279 is_true = is_true || std::strcmp(sptr,
"yes") == 0;
280 is_true = is_true || std::strcmp(sptr,
"Yes") == 0;
281 is_true = is_true || std::strcmp(sptr,
"YES") == 0;
282 is_true = is_true || std::strcmp(sptr,
"t") == 0;
283 is_true = is_true || std::strcmp(sptr,
"T") == 0;
284 is_true = is_true || std::strcmp(sptr,
"true") == 0;
285 is_true = is_true || std::strcmp(sptr,
"True") == 0;
286 is_true = is_true || std::strcmp(sptr,
"TRUE") == 0;
292 bool is_false =
false;
293 is_false = is_false || std::strcmp(sptr,
"n") == 0;
294 is_false = is_false || std::strcmp(sptr,
"N") == 0;
295 is_false = is_false || std::strcmp(sptr,
"no") == 0;
296 is_false = is_false || std::strcmp(sptr,
"No") == 0;
297 is_false = is_false || std::strcmp(sptr,
"NO") == 0;
298 is_false = is_false || std::strcmp(sptr,
"f") == 0;
299 is_false = is_false || std::strcmp(sptr,
"F") == 0;
300 is_false = is_false || std::strcmp(sptr,
"false") == 0;
301 is_false = is_false || std::strcmp(sptr,
"False") == 0;
302 is_false = is_false || std::strcmp(sptr,
"FALSE") == 0;
313 template <
typename T>
314 bool set_value (
const std::string &oname,
const std::string &sval,
315 T *dest,
bool silent, std::ostream &os)
317 std::stringstream ss;
327 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
349 bool set (
const std::string &oname,
const std::string &sval,
bool silent,
351 {
return set_value(oname, sval, &help_, silent, os);}
356 {
return std::string(
"Print this help information");}
359 {
return std::string(
"(false)");}
363 bool help ()
const {
return help_;}
372 template <
typename T>
378 desc_(desc), default_(T()), has_default_(false) {}
380 template <
typename V>
382 desc_(desc), default_(static_cast<T>(val)), has_default_(true) {}
389 {
return has_default_ ? default_val2str(default_) : std::string();}
407 template <
typename U>
408 std::string default_val2str (
const U &val)
const
410 std::stringstream ss;
411 ss <<
'(' << val <<
')';
416 std::string default_val2str (
bool val)
const
417 {
return val ? std::string(
"(true)") :
std::string(
"(false)");}
422 template <
typename T>
430 template <
typename V>
436 bool set (
const std::string &oname,
const std::string &sval,
bool silent,
438 {
return this->
set_value(oname, sval, ptr_, silent, os);}
452 template <
typename T>
460 template <
typename V>
466 bool set (
const std::string &oname,
const std::string &sval,
bool silent,
469 bool success = this->
set_value(oname, sval, &val_, silent, os);
472 ptr_->push_back(val_);
482 ptr_->push_back(val_);
492 std::vector<T> *
const ptr_;
499 typedef std::map<std::string, std::pair<ProgramOption *, std::size_t> >
501 typedef std::list<std::pair<std::string, const ProgramOption *> >
510 option_map_[
"--help"] = std::make_pair(help_ptr_, 0);
511 option_list_.push_back(std::make_pair(
"--help", help_ptr_));
515 silent_(other.silent_), auto_help_(other.auto_help_),
516 option_map_(other.option_map_), option_list_(other.option_list_)
518 for (option_map_type::iterator iter = option_map_.begin();
519 iter != option_map_.end(); ++iter) {
520 if (iter->second.first)
521 iter->second.first = iter->second.first->clone();
527 if (
this != &other) {
528 silent_ = other.silent_;
529 auto_help_ = other.auto_help_;
530 for (option_map_type::iterator iter = option_map_.begin();
531 iter != option_map_.end(); ++iter) {
532 if (iter->second.first)
533 delete iter->second.first;
536 option_map_ = other.option_map_;
537 option_list_ = other.option_list_;
539 for (option_map_type::iterator iter = option_map_.begin();
540 iter != option_map_.end(); ++iter) {
541 if (iter->second.first)
542 iter->second.first = iter->second.first->clone();
549 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
551 silent_(other.silent_), auto_help_(other.auto_help_),
552 help_ptr_(other.help_ptr_),
553 option_map_(cxx11::
move(other.option_map_)),
554 option_list_(cxx11::
move(other.option_list_))
557 other.option_map_.clear();
558 other.option_list_.clear();
563 if (
this != &other) {
564 silent_ = other.silent_;
565 help_ptr_ = other.help_ptr_;
569 other.option_map_.clear();
570 other.option_list_.clear();
579 for (option_map_type::iterator iter = option_map_.begin();
580 iter != option_map_.end(); ++iter) {
582 delete iter->second.first;
592 template <
typename T>
597 const std::string oname(
"--" + name);
599 add_option(oname, optr);
605 template <
typename T,
typename V>
610 const std::string oname(
"--" + name);
612 add_option(oname, optr);
618 template <
typename T>
623 const std::string oname(
"--" + name);
625 add_option(oname, optr);
631 template <
typename T,
typename V>
633 std::vector<T> *ptr, V val)
636 const std::string oname(
"--" + name);
638 add_option(oname, optr);
645 const std::string oname(
"--" + name);
646 option_map_type::iterator iter = option_map_.find(oname);
647 if (iter != option_map_.end()) {
649 delete iter->second.first;
650 option_map_.erase(iter);
651 option_list_type::iterator liter = option_list_find(oname);
652 option_list_.erase(liter);
669 void process (
int argc,
const char **argv, std::ostream &os = std::cout)
672 std::vector<std::string> arg_vector;
673 arg_vector.reserve(static_cast<std::size_t>(argc));
674 for (
int i = 0; i != argc; ++i) {
675 arg = process_arg(argv[i]);
677 arg_vector.push_back(arg);
679 process_arg_vector(arg_vector, os);
683 void process (
int argc,
char **argv, std::ostream &os = std::cout)
686 std::vector<std::string> arg_vector;
687 arg_vector.reserve(static_cast<std::size_t>(argc));
688 for (
int i = 0; i != argc; ++i) {
689 arg = process_arg(argv[i]);
691 arg_vector.push_back(arg);
693 process_arg_vector(arg_vector, os);
699 std::size_t len[2] = {0, 0};
700 std::vector<std::string> vec[3];
701 for (option_list_type::const_iterator liter = option_list_.begin();
702 liter != option_list_.end(); ++liter) {
703 vec[0].push_back(liter->first);
704 vec[1].push_back(liter->second->description());
705 vec[2].push_back(liter->second->default_str());
706 if (len[0] < vec[0].back().size())
707 len[0] = vec[0].back().size();
708 if (len[1] < vec[1].back().size())
709 len[1] = vec[1].back().size();
713 for (std::size_t i = 0; i != vec[0].size(); ++i) {
714 os << vec[0][i] << std::string(len[0] - vec[0][i].size(),
' ');
715 os << vec[1][i] << std::string(len[1] - vec[1][i].size(),
' ');
716 os << vec[2][i] << std::endl;
721 std::size_t
count (
const std::string &name)
const
723 option_map_type::const_iterator iter = option_map_.find(
"--" + name);
724 if (iter != option_map_.end())
725 return iter->second.second;
733 option_map_type::const_iterator iter = option_map_.find(
"--" + name);
734 if (iter != option_map_.end())
735 return iter->second.first;
743 option_map_type::const_iterator iter = option_map_.find(
"--" + name);
744 if (iter != option_map_.end())
745 return iter->second.first;
752 void silent (
bool flag) {silent_ = flag;}
763 option_map_type option_map_;
764 option_list_type option_list_;
766 option_list_type::iterator option_list_find (
const std::string &oname)
768 option_list_type::iterator liter = option_list_.begin();
769 for (; liter != option_list_.end(); ++liter) {
770 if (liter->first == oname)
777 void add_option (
const std::string &oname, ProgramOption *optr)
779 std::pair<option_map_type::iterator, bool> insert =
780 option_map_.insert(std::make_pair(oname, std::make_pair(optr, 0)));
782 option_list_.push_back(std::make_pair(oname, optr));
785 delete insert.first->second.first;
786 insert.first->second.first = optr;
787 option_list_type::iterator liter = option_list_find(oname);
788 liter->second = optr;
792 void process_arg_vector (std::vector<std::string> &arg_vector,
795 std::string option_value;
796 const std::vector<std::string> option_value_vec;
797 std::vector<std::pair<std::string, std::vector<std::string> > >
799 std::vector<std::string>::iterator aiter = arg_vector.begin();
800 while (aiter != arg_vector.end() && !is_option(*aiter))
802 while (aiter != arg_vector.end()) {
803 option_vector.push_back(std::make_pair(*aiter, option_value_vec));
804 std::vector<std::string> &value = option_vector.back().second;
806 while (aiter != arg_vector.end() &&!is_option(*aiter)) {
807 value.push_back(*aiter);
812 const std::string sval_true(
"1");
813 for (std::vector<std::pair<std::string, std::vector<std::string> > >::
814 iterator iter = option_vector.begin();
815 iter != option_vector.end(); ++iter) {
816 option_map_type::iterator miter = option_map_.find(iter->first);
817 if (miter == option_map_.end()) {
824 const std::size_t vsize = iter->second.size();
825 if (vsize == 0 && miter->second.first->is_bool()) {
826 proc = process_option(miter, sval_true, os);
827 }
else if (vsize == 0) {
830 }
else if (!miter->second.first->is_vector()) {
831 option_value.clear();
832 for (std::size_t i = 0; i != vsize - 1; ++i)
833 option_value += iter->second[i] +
' ';
834 option_value += iter->second[vsize - 1];
835 proc = process_option(miter, option_value, os);
837 for (std::size_t i = 0; i != vsize; ++i)
838 proc = process_option(miter, iter->second[i], os) || proc;
841 ++miter->second.second;
844 for (option_map_type::iterator iter = option_map_.begin();
845 iter != option_map_.end(); ++iter) {
846 if (iter->second.second == 0)
847 if (iter->second.first->set_default())
848 iter->second.second = 1;
851 if (auto_help_ && help_ptr_->
help())
855 std::string process_arg (
const char *arg)
const
857 std::size_t s = std::strlen(arg);
859 while (e != 0 && (arg[e - 1] ==
' ' || arg[e - 1] ==
','))
862 return std::string(arg, arg + e);
865 bool process_option (option_map_type::iterator iter,
866 const std::string &sval, std::ostream &os)
873 return iter->second.first->set(iter->first, sval, silent_, os);
876 bool is_option (
const std::string &str)
const
893 #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
bool set(const std::string &oname, const std::string &sval, bool silent, std::ostream &os)
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.
virtual ProgramOption * clone() const =0
ProgramOptionMap & operator=(const ProgramOptionMap &other)
ProgramOptionDefault(const std::string &desc)
ProgramOption * clone() const
std::string description() const
ProgramOption(const ProgramOption &)
virtual bool is_vector() const =0
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)
ProgramOptionDefault(const std::string &desc, V val)
ProgramOptionVector(const std::string &desc, std::vector< T > *ptr)
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.
remove_reference< T >::type && move(T &&t) noexcept
#define VSMC_NULLPTR
nullptr
ProgramOption * clone() const
virtual bool set(const std::string &, const std::string &, bool, std::ostream &)=0
#define VSMC_RUNTIME_ASSERT_UTILITY_PROGRAM_OPTION_NULLPTR(ptr, func)
const ProgramOption * option(const std::string &name) const
Get the underlying option object.
std::string default_str() const
virtual bool is_bool() const =0
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.
virtual std::string default_str() const =0
void process(int argc, char **argv, std::ostream &os=std::cout)
Process the options.
virtual std::string description() const =0
Option with a default value.
std::size_t count(const std::string &name) const
Count the number of successful processing of an option.
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(const std::string &oname, const std::string &sval, bool silent, std::ostream &os)
bool set(const std::string &oname, const std::string &sval, bool silent, std::ostream &os)
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 ...