1 #ifndef MSP_CORE_GETOPT_H_
2 #define MSP_CORE_GETOPT_H_
8 #include <msp/strings/lexicalcast.h>
12 class usage_error: public std::runtime_error
18 usage_error(const std::string &w, const std::string &h = std::string()): std::runtime_error(w), help_(h) { }
19 ~usage_error() throw() { }
21 const char *help() const throw() { return help_.c_str(); }
42 virtual Option &set_help(const std::string &) = 0;
43 virtual Option &set_help(const std::string &, const std::string &) = 0;
44 virtual unsigned get_seen_count() const = 0;
48 class OptBase: public Option
58 OptBase(char, const std::string &, ArgType);
60 virtual ~OptBase() { }
62 virtual OptBase &set_help(const std::string &);
63 virtual OptBase &set_help(const std::string &, const std::string &);
64 char get_short() const { return shrt; }
65 const std::string &get_long() const { return lng; }
66 ArgType get_arg_type() const { return arg_type; }
67 const std::string &get_help() const { return help; }
68 const std::string &get_metavar() const { return metavar; }
69 virtual unsigned get_seen_count() const { return seen_count; }
71 void process(const std::string &);
73 virtual void store() = 0;
74 virtual void store(const std::string &) = 0;
78 class SimpleOption: public OptBase
84 SimpleOption(char s, const std::string &l, T &d, ArgType a): OptBase(s, l, a), data(d) { }
86 virtual void store() { }
88 virtual void store(const std::string &a)
92 data = lexical_cast<T>(a);
94 catch(const lexical_error &e)
96 throw usage_error("Invalid argument for --"+lng+" ("+e.what()+")");
102 class ListOption: public OptBase
108 ListOption(char s, const std::string &l, T &d, ArgType a): OptBase(s, l, a), data(d)
109 { if(arg_type!=REQUIRED_ARG) throw std::invalid_argument("ListOption arg_type!=REQUIRED"); }
111 virtual void store() { }
113 virtual void store(const std::string &a)
117 data.push_back(lexical_cast<typename T::value_type>(a));
119 catch(const lexical_error &e)
121 throw usage_error("Invalid argument for --"+lng+" ("+e.what()+")");
127 std::list<OptBase *> opts;
128 std::vector<std::string> args;
134 const std::vector<std::string> &get_args() const { return args; }
137 Option &add_option(char s, const std::string &l, T &d, ArgType a = NO_ARG)
138 { return add_option(new SimpleOption<T>(s, l, d, a)); }
141 Option &add_option(char s, const std::string &l, std::list<T> &d, ArgType a = REQUIRED_ARG)
142 { return add_option(new ListOption<std::list<T> >(s, l, d, a)); }
145 Option &add_option(const std::string &l, T &d, ArgType a)
146 { return add_option(0, l, d, a); }
149 OptBase &add_option(OptBase *);
151 OptBase &get_option(char);
152 OptBase &get_option(const std::string &);
155 /** Processes argc/argv style command line arguments. The contents of argv
156 will be unchanged; use get_args to access non-option arguments. */
157 void operator()(unsigned, const char *const *);
160 /** Processes a long option. Returns the number of arguments eaten. */
161 unsigned process_long(const char *const *);
163 /** Processes short options. Returns the number of arguments eaten. */
164 unsigned process_short(const char *const *);
167 /** Generates a single line that describes known options. */
168 std::string generate_usage(const std::string &) const;
170 /** Generates help for known options in tabular format, one option per
171 line. The returned string will have a linefeed at the end. */
172 std::string generate_help() const;
175 template<> inline void GetOpt::SimpleOption<bool>::store()
178 template<> inline void GetOpt::SimpleOption<unsigned>::store()
181 template<> inline void GetOpt::SimpleOption<std::string>::store(const std::string &a)
184 template<> inline void GetOpt::ListOption<std::list<std::string> >::store(const std::string &a)
185 { data.push_back(a); }