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