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 ...