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