#ifndef PROGRAM_OPTIONS_H #define PROGRAM_OPTIONS_H /* wraps boost options_description as printable_opts - show the options values used as well as defaults in usage or log messages. boost program options library lacks any concept of printing configured values; it only supports parsing them from strings */ #ifdef _WIN32 #include #endif #include #include #include #include #include // change --opt-name=x --opt_name=x for all strings x. danger: probably the argv from int main isn't supposed to be modified? inline int arg_minusto_underscore(char *s) { if (!*s || *s++ != '-') return 0; if (!*s || *s++ != '-') return 0; int chars_replaced=0; for(;*s;++s) { if (*s=='=') break; if (*s=='-') { *s='_'; ++chars_replaced; } } return chars_replaced; } inline int argv_minus_to_underscore(int argc, char **argv) { int chars_replaced=0; for (int i=1;i boost::program_options::typed_value* defaulted_value(T *v) { return boost::program_options::value(v)->default_value(*v); } inline void program_options_fatal(std::string const& msg) { throw std::runtime_error(msg); } inline std::string const& get_single_arg(boost::any& v,std::vector const& values) { boost::program_options::validators::check_first_occurrence(v); return boost::program_options::validators::get_single_string(values); } template void must_complete_read(I &in,std::string const& msg="Couldn't parse") { char c; if (in.bad()) program_options_fatal(msg + " - failed input"); if (in >> c) program_options_fatal(msg + " - got extra char: " + std::string(c,1)); } template struct any_printer : public boost::function { typedef boost::function F; template struct typed_print { void operator()(Ostream &o,boost::any const& t) const { o << *boost::any_cast(&t); } }; template static void typed_print_template(Ostream &o,boost::any const& t) { o << *boost::any_cast(&t); } any_printer() {} any_printer(const any_printer& x) : F(static_cast(x)) {} template explicit any_printer(T const*) : F(typed_print()) { } template void set() { F f(typed_print()); swap(f); } }; // have to wrap regular options_description and store our own tables because // author didn't make enough stuff protected/public or add a virtual print // method to value_semantic template struct printable_options_description : public boost::program_options::options_description { typedef printable_options_description self_type; typedef boost::program_options::options_description options_description; typedef boost::program_options::option_description option_description; typedef boost::shared_ptr group_type; typedef std::vector groups_type; struct printable_option { typedef boost::shared_ptr OD; any_printer print; OD od; bool in_group; std::string const& name() { return od->long_name(); } std::string const& description() { return od->description(); } std::string const& vmkey() { return od->key(name()); } template printable_option(T *tag, OD const& od) : print(tag),od(od),in_group(false) {} printable_option() : in_group(false) {} }; typedef std::vector options_type; BOOST_STATIC_CONSTANT(unsigned,default_linewrap=80); // options_description::m_default_line_length printable_options_description(unsigned line_length = default_linewrap) : options_description(line_length) {} printable_options_description(const std::string& caption, unsigned line_length = default_linewrap) : options_description(caption,line_length), caption(caption) {} self_type &add_options() { return *this; } template self_type & operator()(char const* name, boost::program_options::typed_value *val, char const*description=NULL) { printable_option opt((T *)0,simple_add(name,val,description)); pr_options.push_back(opt); return *this; } self_type& add(self_type const& desc) { options_description::add(desc); groups.push_back(group_type(new self_type(desc))); for (typename options_type::const_iterator i=desc.pr_options.begin(),e=desc.pr_options.end(); i!=e;++i) { pr_options.push_back(*i); pr_options.back().in_group=true; } return *this; } void print_option(Ostream &o, printable_option &opt, boost::program_options::variable_value const & var, bool only_value=false) { using namespace boost; using namespace boost::program_options; using namespace std; string const& name=opt.name(); if (!only_value) { if (var.defaulted()) o << "#DEFAULTED# "; if (var.empty()) { o << "#EMPTY# "<print(o,vm,show_flags); } /// parses arguments, then stores/notifies from opts->vm. returns unparsed /// options and positional arguments, but if not empty, throws exception unless /// allow_unrecognized_positional is true std::vector parse_options(int argc,char **argv, boost::program_options::variables_map &vm, boost::program_options::positional_options_description *po=NULL, bool allow_unrecognized_positional=false, bool allow_unrecognized_opts=false) { using namespace boost::program_options; using namespace std; command_line_parser cl(argc,argv); cl.options(*this); if (po) cl.positional(*po); if (allow_unrecognized_opts) cl.allow_unregistered(); parsed_options parsed=cl.run(); vector unparsed=collect_unrecognized(parsed.options, po ? exclude_positional : include_positional); if (!allow_unrecognized_positional) { if (!unparsed.empty()) program_options_fatal("Unrecognized argument: "+unparsed.front()); } store(parsed,vm); notify(vm); return unparsed; } std::vector parse_options(int argc,char const*argv[], boost::program_options::variables_map &vm, boost::program_options::positional_options_description *po=NULL, bool allow_unrecognized_positional=false, bool allow_unrecognized_opts=false) { return parse_options(argc,const_cast(argv),vm,po ,allow_unrecognized_positional,allow_unrecognized_opts); } private: groups_type groups; options_type pr_options; std::string caption; boost::shared_ptr simple_add(const char* name, const boost::program_options::value_semantic* s, const char * description = NULL) { typedef option_description OD; boost::shared_ptr od( (description ? new OD(name,s,description) : new OD(name,s)) ); options_description::add(od); return od; } }; typedef printable_options_description printable_opts; #endif