]> git.tdb.fi Git - libs/core.git/blob - source/core/getopt.h
Drop copyright and license notices from source files
[libs/core.git] / source / core / getopt.h
1 #ifndef MSP_CORE_GETOPT_H_
2 #define MSP_CORE_GETOPT_H_
3
4 #include <list>
5 #include <stdexcept>
6 #include <string>
7 #include <vector>
8 #include <msp/strings/lexicalcast.h>
9
10 namespace Msp {
11
12 class usage_error: public std::runtime_error
13 {
14 private:
15         std::string help_;
16
17 public:
18         usage_error(const std::string &w, const std::string &h = std::string()): std::runtime_error(w), help_(h) { }
19         ~usage_error() throw() { }
20
21         const char *help() const throw() { return help_.c_str(); }
22 };
23
24
25 class GetOpt
26 {
27 public:
28         enum ArgType
29         {
30                 NO_ARG,
31                 OPTIONAL_ARG,
32                 REQUIRED_ARG
33         };
34         
35         class OptBase
36         {
37         protected:
38                 char shrt;
39                 std::string lng;
40                 ArgType arg_type;
41                 unsigned seen_count;
42                 std::string help;
43                 std::string metavar;
44
45                 OptBase(char, const std::string &, ArgType);
46         public:
47                 virtual ~OptBase() { }
48
49                 OptBase &set_help(const std::string &);
50                 OptBase &set_help(const std::string &, const std::string &);
51                 char get_short() const { return shrt; }
52                 const std::string &get_long() const { return lng; }
53                 ArgType get_arg_type() const { return arg_type; }
54                 const std::string &get_help() const { return help; }
55                 const std::string &get_metavar() const { return metavar; }
56                 unsigned get_seen_count() const { return seen_count; }
57                 void process();
58                 void process(const std::string &);
59         protected:
60                 virtual void store() = 0;
61                 virtual void store(const std::string &) = 0;
62         };
63
64 private:
65         template<typename T>
66         class Option: public OptBase
67         {
68         public:
69                 Option(char s, const std::string &l, T &d, ArgType a): OptBase(s, l, a), data(d) { }
70
71                 virtual void store() { }
72
73                 virtual void store(const std::string &a)
74                 {
75                         try
76                         {
77                                 data = lexical_cast<T>(a);
78                         }
79                         catch(const lexical_error &e)
80                         {
81                                 throw usage_error("Invalid argument for --"+lng+" ("+e.what()+")");
82                         }
83                 }
84         private:
85                 T &data;
86         };
87
88         template<typename T>
89         class ListOption: public OptBase
90         {
91         public:
92                 ListOption(char s, const std::string &l, T &d, ArgType a): OptBase(s, l, a), data(d)
93                 { if(arg_type!=REQUIRED_ARG) throw std::invalid_argument("ListOption arg_type!=REQUIRED"); }
94
95                 virtual void store() { }
96
97                 virtual void store(const std::string &a)
98                 {
99                         try
100                         {
101                                 data.push_back(lexical_cast<typename T::value_type>(a));
102                         }
103                         catch(const lexical_error &e)
104                         {
105                                 throw usage_error("Invalid argument for --"+lng+" ("+e.what()+")");
106                         }
107                 }
108         private:
109                 T &data;
110         };
111
112         bool help;
113         std::list<OptBase *> opts;
114         std::vector<std::string> args;
115
116 public:
117         GetOpt();
118         ~GetOpt();
119
120         const std::vector<std::string> &get_args() const { return args; }
121
122         template<typename T>
123         OptBase &add_option(char s, const std::string &l, T &d, ArgType a = NO_ARG)
124         { opts.push_back(new Option<T>(s, l, d, a)); return *opts.back(); }
125         
126         template<typename T>
127         OptBase &add_option(char s, const std::string &l, std::list<T> &d, ArgType a = REQUIRED_ARG)
128         { opts.push_back(new ListOption<std::list<T> >(s, l, d, a)); return *opts.back(); }
129         
130         template<typename T>
131         OptBase &add_option(const std::string &l, T &d, ArgType a)
132         { return add_option(0, l, d, a); }
133
134 private:
135         OptBase &get_option(char);
136         OptBase &get_option(const std::string &);
137
138 public:
139         /** Processes argc/argv style command line arguments.  The contents of argv
140         will be unchanged; use get_args to access non-option arguments. */
141         void operator()(unsigned, const char *const *);
142
143 private:
144         /** Processes a long option.  Returns the number of arguments eaten. */
145         unsigned process_long(const char *const *);
146
147         /** Processes short options.  Returns the number of arguments eaten. */
148         unsigned process_short(const char *const *);
149
150 public:
151         /** Generates a single line that describes known options. */
152         std::string generate_usage(const std::string &) const;
153
154         /** Generates help for known options in tabular format, one option per
155         line.  The returned string will have a linefeed at the end. */
156         std::string generate_help() const;
157 };
158
159 template<> inline void GetOpt::Option<bool>::store()     { data = true; }
160 template<> inline void GetOpt::Option<unsigned>::store() { ++data; }
161
162 template<> inline void GetOpt::Option<std::string>::store(const std::string &a)
163 { data = a; }
164
165 template<> inline void GetOpt::ListOption<std::list<std::string> >::store(const std::string &a)
166 { data.push_back(a); }
167
168 } // namespace Msp
169
170 #endif