Add try-catch block in example in order to fix memory leaks. Added specialized except...
[command.git] / include / option.h
1 #ifndef __COMMAND_OPTION_H
2 #define __COMMAND_OPTION_H
3
4 #include <string>
5 #include <sstream>
6 #include <stdexcept>
7
8 #include "parameter.h"
9 #include "exception/missingOptionValue.h"
10 #include "exception/optionFailedConversion.h"
11
12 namespace command {
13     /**
14      * Class responsible for handling commandline options.
15      * Options are named parameters of program.
16      *
17      * Example:
18      *  - ./myprog OptionName=OptionValue
19      *  - ./myprog -f=/some/file
20      *  - ./myprog --level=15
21      */
22     template<typename ParameterType>
23     class Option
24         : public Parameter, public Callable<ParameterType>  {
25     public:
26         typedef std::string OptionName;
27     protected:
28         /**
29          * Current Option name
30          */
31         const OptionName name;
32
33         /**
34          * Current Option value
35          */
36         ParameterType value;
37
38     public:
39         /**
40          * Default constructor.
41          *
42          * @param name Name of the current Option
43          * @param description Description of current Option
44          * @param function Function used to handle current Option.
45          */
46         Option(const std::string & name, const std::string & description, void (*function)(ParameterType))
47             : Parameter(description), Callable<ParameterType>(function), name(name) {
48         }
49
50         /**
51          *
52          */
53         virtual ~Option() { }
54
55         /**
56          * \inheritdoc
57          */
58         virtual void handle() {
59             this->call(value);
60         }
61
62         /**
63          * Method used for checking if Option understands given user value.
64          * If so current Option is flagged as used and no more checks against
65          * it will be done in future.
66          *
67          * Passed value should be in form of:
68          *      OptionName=OptionValue
69          *
70          * If no equal sign is after OptionName part,
71          * std::invalid_argument exception with appropriate message is thrown
72          *
73          * If conversion of OptionValue part to ParameterType failed,
74          * std::invalid_argument exception with appropriate message is thrown
75          *
76          * @param argv command line value against which test will be made.
77          *  User value should be in format: OptionName=OptionValue.
78          *
79          * @return If passed argv succesfully detected OptionName part as a
80          *  current option and its OptionValue part has been succesfully
81          *  converted to ParameterType, returns true and Option is set as used one.
82          *  Otherwise returns false and can be used to check against next value.
83          *
84          * @throw MissingOptionValue when OptionValue part is missing after
85          *  equal sign
86          * @throw OptionFailedConversion when OptionValue part failed conversion
87          *  to ParameterType
88          */
89         virtual bool understand(const std::string & argv) {
90
91             if ((!isUsed()) && (argv.find(name) == 0)) {
92                 std::size_t pos = argv.find("=");
93
94                 if (pos != name.size()) {
95                     throw MissingOptionValue("Option: " + name + " requires value but no one has been provided");
96                 }
97
98                 std::stringstream ss;
99                 ss << argv.substr(pos + 1);
100                 ss >> value;
101
102                 if (ss.fail()) {
103                     throw OptionFailedConversion("Value for option: " + name + " failed conversion to the required type");
104                 }
105
106                 used = true;
107                 return true;
108             }
109             return false;
110         }
111     };
112
113     /**
114      * Template class responsible for handling commandline options.
115      * Options are non-required, named parameters of program.
116      * This template specialization allows Options to work like switches.
117      * It means that just named parameter is needed to invoke command. No value
118      * is used.
119      *
120      * Example:
121      *  ./myprog OptionName
122      *  ./myprog -h
123      *  ./myprog --help
124      */
125     template<>
126     class Option<void>
127         : public Parameter, public Callable<void>  {
128     public:
129         typedef std::string OptionName;
130     protected:
131         /**
132          * Current Option name
133          */
134         const OptionName name;
135     public:
136         /**
137          * Default constructor.
138          *
139          * @param name Name of the current Option
140          * @param description Description of current Option
141          * @param function Function used to handle current Option.
142          */
143         Option(const std::string & name, const std::string & description, void (*function)(void))
144             : Parameter(description), Callable<void>(function), name(name) {
145         }
146
147         /**
148          *
149          */
150         virtual void handle() {
151             this->call();
152         }
153
154         /**
155          * Method used for checking if Option understands given user value.
156          * If so, current Option is flagged as used and no more checks against
157          * it will be done in future.
158          *
159          * Passed value should be in form of:
160          *      OptionName
161          *
162          * @param argv command line value against which test will be made.
163          *  User value should be in format: OptionName.
164          *
165          * @return If passed argv succesfully detected OptionName returns true
166          *  and Option is set as used one. Otherwise returns false and can be
167          *  used to check against next value.
168          */
169         virtual bool understand(const std::string & argv) {
170             if ((!isUsed()) &&
171                 (argv == name)) {
172                 used = true;
173                 return true;
174             }
175             return false;
176         }
177     };
178 }
179
180 #endif /* __COMMAND_OPTION_H */